diff --git a/.ci/get_solved_issues-github-actions.py b/.ci/get_solved_issues-github-actions.py deleted file mode 100644 index 26cce80165b3c..0000000000000 --- a/.ci/get_solved_issues-github-actions.py +++ /dev/null @@ -1,81 +0,0 @@ -#! /usr/bin/env python -# -# Harvest the solved issues for a certain tag and print them out in a format -# which is ready to be pasted in the release notes. -# -# Copyright (c) 2024 Rene Brun and Fons Rademakers -# Author: Enrico Guiraud, Axel Naumann, Danilo Piparo - -from github3 import GitHub -from argparse import ArgumentParser -import sys, os, re - -token = os.environ["GITHUB_TOKEN"] - -def parse_args(): - p = ArgumentParser() - g = p.add_mutually_exclusive_group(required=True) - g.add_argument( - "--project-name", - type=str, - dest="name", - help="GitHub project name, or part of it", - ) - return p.parse_args() - - -def format_solved_issue(number: int, title: str, url: str) -> str: - return f"* [[#{number}]({url})] - {title}" - - -def print_fmtted_issues(): - repo = GitHub(token=token).repository("root-project", "root") - args = parse_args() - name_pattern_str = args.name - if name_pattern_str[0] == 'v': name_pattern_str = name_pattern_str[1:] - # Don't care about "." or "/" or "-" delimiting version number parts: - name_pattern = re.compile(r''.join([r'\W' if not char.isalnum() else char for char in name_pattern_str])) - def matches(project): - return name_pattern.search(project.name) - - repo_projects_str = " ".join(repo.projects()) - print(f"List of projects in the repository: {repo_projects_str}") - - pro = [p for p in repo.projects() if matches(p)] - if len(pro) != 1: - print( - "Could not identify a unique GitHub project in root-project/root with " - f"name containing {name_pattern_str}", - file=sys.stderr, - ) - sys.exit(1) - pro = pro[0] - - col = list(pro.columns()) - if len(col) != 1: - print(f"Project '{pro.name}' has more than one column", file=sys.stderr) - sys.exit(2) - col = col[0] - - issues_and_prs = [card.retrieve_issue_from_content() for card in col.cards()] - issues = [i for i in issues_and_prs if i.pull_request() is None] - sored_issues = sorted(issues, key = lambda i: -1 * i.number) - fmtted_issues = [format_solved_issue(i.number, i.title, i.html_url) for i in sored_issues] - print(pro.name) - print('### Bugs and Issues fixed in this release\n') - for i in fmtted_issues: - print(i) - - prs = [format_solved_issue(i.number, i.title, i.html_url) for i in issues if i.pull_request() is not None] - # check we did not miss anything and we did not count anything twice - assert(len(issues) == len(fmtted_issues) + len(prs)) - if len(prs) > 0: - print("") - - -if __name__ == "__main__": - print_fmtted_issues() diff --git a/.github/workflows/code_analysis.yml b/.github/workflows/code_analysis.yml index e1d32abdd75d4..b76fa9880398b 100644 --- a/.github/workflows/code_analysis.yml +++ b/.github/workflows/code_analysis.yml @@ -90,8 +90,8 @@ jobs: run: | files=$(grep '\.py$' changed_files.txt || echo "") if [ -n "$files" ]; then - diff_command="" apply_command="" + failure=false for file in $files; do while IFS=- read -r start length; do [ -z "$start" ] && continue @@ -101,20 +101,14 @@ jobs: continue fi end=$((start + length)) - diff_command+="ruff format --diff --range $start-$end $file && " + ruff format --diff --preview --range ${start}-${end} ${file} || failure=true apply_command+="ruff format --range $start-$end $file && " done < <(git diff --unified=0 HEAD~1 -- "$file" | grep '^@@' | sed -E 's/^@@ -[0-9]+(,[0-9]+)? \+([0-9]+)(,([0-9]+))? @@.*/\2-\4/') done - if [ -n "$diff_command" ]; then - diff_command=${diff_command% && } - if ! eval "$diff_command"; then - apply_command=${apply_command% && } - echo -e "::error::Formatting failed. To apply the changes locally, run the following command:\n$apply_command" - exit 123 - fi - else - echo "No ranges detected to format." + if ${failure}; then + echo -e "::error::Formatting failed. To apply the changes locally, run the following command:\n$apply_command" + exit 123; fi else echo "No python files to format" diff --git a/.github/workflows/projFixedIssues.yml b/.github/workflows/projFixedIssues.yml index 76b890d204a45..799e87e2eaf0a 100644 --- a/.github/workflows/projFixedIssues.yml +++ b/.github/workflows/projFixedIssues.yml @@ -3,24 +3,60 @@ name: 'GetFixedIssues' on: workflow_dispatch: inputs: - tag: - description: Generate the release notes of fixed issues for this tag (e.g. "v6-32-12") - type: string + major: + type: choice + description: Major + options: + - 6 + - 7 + - 8 required: true + default: 6 + minor: + type: choice + description: Minor + options: + - 26 + - 28 + - 30 + - 32 + - 36 + - 38 + - 40 + - 42 + - 44 + - 46 + - 48 + required: true + default: 40 + patch: + type: choice + description: Patch + options: + - "00" + - "02" + - "04" + - "06" + - "08" + - "10" + - "12" + - "14" + - "16" + - "18" + - "20" + - "22" + - "24" + - "26" + - "28" + - "30" + required: true + default: "00" jobs: check-tag: runs-on: ubuntu-latest steps: - - name: Set up Python - uses: actions/setup-python@v5 - - name: Install python dependencies - run: | - pip install github3.py - - name: Download issue extraction script - run: | - wget https://raw.githubusercontent.com/root-project/root/master/.ci/get_solved_issues-github-actions.py - name: Generate list of closed issues for release notes env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: python ./get_solved_issues-github-actions.py --project-name ${{ inputs.tag }} + run: gh project item-list `gh project list --owner root-project |grep ${{ inputs.major }}.${{ inputs.minor }}.${{ inputs.patch }}|awk '{print $1}'` --owner root-project -L 8192|grep "Issue"|sort -t$'\t' -k3 -n -r| awk -v FS='\t' -v OFS='\t' '{print " * [[#"$3"](https://github.com/root-project/root/issues/"$3")] - "$2}' diff --git a/.github/workflows/root-ci-config/buildconfig/alma10-benchmark.txt b/.github/workflows/root-ci-config/buildconfig/alma10-benchmark.txt index 99f88be784e71..ce7742559e68f 100644 --- a/.github/workflows/root-ci-config/buildconfig/alma10-benchmark.txt +++ b/.github/workflows/root-ci-config/buildconfig/alma10-benchmark.txt @@ -1,7 +1,5 @@ CMAKE_CXX_STANDARD=20 builtin_vdt=ON -builtin_zlib=ON -builtin_zstd=ON pythia8=ON r=OFF rootbench=ON diff --git a/.github/workflows/root-ci-config/buildconfig/alma10-clang_ninja.txt b/.github/workflows/root-ci-config/buildconfig/alma10-clang_ninja.txt index 7512de26c3071..1ecdd6500b5d4 100644 --- a/.github/workflows/root-ci-config/buildconfig/alma10-clang_ninja.txt +++ b/.github/workflows/root-ci-config/buildconfig/alma10-clang_ninja.txt @@ -1,12 +1,14 @@ CMAKE_C_COMPILER=clang CMAKE_CXX_COMPILER=clang++ CMAKE_GENERATOR=Ninja -builtin_vdt=ON +builtin_freetype=ON builtin_gif=ON +builtin_gl2ps=ON builtin_jpeg=ON -builtin_png=ON builtin_lz4=ON builtin_lzma=ON +builtin_png=ON +builtin_vdt=ON builtin_zlib=ON builtin_zstd=ON pythia8=ON diff --git a/.github/workflows/root-ci-config/buildconfig/alma10-minimal.txt b/.github/workflows/root-ci-config/buildconfig/alma10-minimal.txt index c98f232c6151f..a05a0aea30429 100644 --- a/.github/workflows/root-ci-config/buildconfig/alma10-minimal.txt +++ b/.github/workflows/root-ci-config/buildconfig/alma10-minimal.txt @@ -1,7 +1,5 @@ ccache=ON builtin_vdt=ON -builtin_zlib=ON -builtin_zstd=ON fail-on-missing=ON minimal=ON roottest=ON diff --git a/.github/workflows/root-ci-config/buildconfig/alma10.txt b/.github/workflows/root-ci-config/buildconfig/alma10.txt index 0a84001142aaa..f265d40f10e5a 100644 --- a/.github/workflows/root-ci-config/buildconfig/alma10.txt +++ b/.github/workflows/root-ci-config/buildconfig/alma10.txt @@ -1,5 +1,3 @@ builtin_vdt=ON -builtin_zlib=ON -builtin_zstd=ON pythia8=ON r=OFF diff --git a/.github/workflows/root-ci-config/buildconfig/fedora43.txt b/.github/workflows/root-ci-config/buildconfig/fedora43.txt index 3563fe5a20b6a..465ff7b6fa487 100644 --- a/.github/workflows/root-ci-config/buildconfig/fedora43.txt +++ b/.github/workflows/root-ci-config/buildconfig/fedora43.txt @@ -1,6 +1,4 @@ CMAKE_CXX_STANDARD=23 -builtin_zlib=ON -builtin_zstd=ON experimental_adaptivecpp=ON pythia8=ON roofit_multiprocess=ON diff --git a/.github/workflows/root-ci-config/buildconfig/fedora44.txt b/.github/workflows/root-ci-config/buildconfig/fedora44.txt index a01ed2484f58a..b4c72b29cadc9 100644 --- a/.github/workflows/root-ci-config/buildconfig/fedora44.txt +++ b/.github/workflows/root-ci-config/buildconfig/fedora44.txt @@ -1,6 +1,4 @@ CMAKE_CXX_STANDARD=23 -builtin_zlib=ON -builtin_zstd=ON experimental_adaptivecpp=ON pythia8=ON roofit_multiprocess=ON diff --git a/.github/workflows/root-ci-config/buildconfig/rawhide.txt b/.github/workflows/root-ci-config/buildconfig/rawhide.txt index a1098e2f490e0..393a11a08eaf8 100644 --- a/.github/workflows/root-ci-config/buildconfig/rawhide.txt +++ b/.github/workflows/root-ci-config/buildconfig/rawhide.txt @@ -1,5 +1,3 @@ -builtin_zlib=ON -builtin_zstd=ON pythia8=ON test_distrdf_dask=OFF test_distrdf_pyspark=OFF diff --git a/.github/workflows/visual-studio-latest.yml b/.github/workflows/visual-studio-latest.yml index e9d79c018c719..d29fb2750c515 100644 --- a/.github/workflows/visual-studio-latest.yml +++ b/.github/workflows/visual-studio-latest.yml @@ -29,11 +29,13 @@ jobs: run: "type C:\\ROOT-CI\\VS-Update.log" - name: Checkout + if: ${{ always() }} uses: actions/checkout@v6 with: ref: master - name: Build after VS update + if: ${{ !cancelled() }} shell: cmd run: "C:\\setenv.bat x64 && python .github/workflows/root-ci-config/build_root.py diff --git a/.github/workflows/visual-studio-preview.yml b/.github/workflows/visual-studio-preview.yml index 57357c06a0ff7..e96a8400ea762 100644 --- a/.github/workflows/visual-studio-preview.yml +++ b/.github/workflows/visual-studio-preview.yml @@ -29,11 +29,13 @@ jobs: run: "type C:\\ROOT-CI\\VS-Update.log" - name: Checkout + if: ${{ always() }} uses: actions/checkout@v6 with: ref: master - name: Build after VS update + if: ${{ !cancelled() }} shell: cmd run: "C:\\setenv.bat x64 && python .github/workflows/root-ci-config/build_root.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 146a23312ca38..2b092fe9f969b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,8 +240,6 @@ if(ccache) if(EXISTS ${CCACHE_COMMAND}) message(STATUS "Found ccache: ${CCACHE_COMMAND}") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_COMMAND}) - execute_process(COMMAND ${CCACHE_COMMAND} "-V" OUTPUT_VARIABLE CCACHE_VERSION) - string(REGEX REPLACE "ccache version ([0-9\\.]+).*" "\\1" CCACHE_VERSION ${CCACHE_VERSION}) else() message(STATUS "Could NOT find ccache") set(ccache OFF CACHE BOOL "Use ccache (disabled since ccache was not found)" FORCE) @@ -411,6 +409,9 @@ else() if(asimage) message(SEND_ERROR "minimal=ON is not compatible with asimage=ON. Consider setting instead gminimal=ON") endif() + if(asimage_tiff) + message(SEND_ERROR "minimal=ON is not compatible with asimage_tiff=ON. Consider setting instead gminimal=ON") + endif() if(x11) message(SEND_ERROR "minimal=ON is not compatible with x11=ON. Consider setting instead gminimal=ON") endif() diff --git a/README/ReleaseNotes/v640/index.md b/README/ReleaseNotes/v640/index.md index bf2ae6264b139..daa35ae22ff65 100644 --- a/README/ReleaseNotes/v640/index.md +++ b/README/ReleaseNotes/v640/index.md @@ -25,6 +25,7 @@ The following people have contributed to this new version: David Lange, CERN and Princeton,\ Sergey Linev, GSI Darmstadt,\ Lorenzo Moneta, CERN/EP-SFT,\ + Christian Ng, https://laserbear.org,\ Vincenzo Eduardo Padulano, CERN/EP-SFT,\ Giacomo Parolini, CERN/EP-SFT,\ Danilo Piparo, CERN/EP-SFT,\ @@ -48,6 +49,11 @@ The following people have contributed to this new version: The ZeroMQ library and its C++ bindings are used by the experimental RooFit multiprocessing package, enabled by the `roofit_multiprocess` build option. The ZeroMQ versions it requires (>=4.3.6 or 4.3.5 with the draft API) are now available in the package managers of several platforms, for example Conda, Homebrew, Fedora and the Extra Packages for Enterprise Linux (EPEL). The `roofit_multiprocess` feature is only required by a small set of RooFit power uses, who are using one of these environments and therefore don't require the builtin ZeroMQ library. +* The overloads of `RooAbsReal::createChi2()` and `RooAbsReal::chi2FitTo()` that take unbinned **RooDataSet** data objects are deprecated and will be removed in ROOT 6.42. + These methods implemented a specialized chi-square fit for x-y-data with errors in y and optional errors in x, which is conceptually different from the standard histogram-based chi-square in the **RooDataHist** case and can lead to ambiguous results. + To fit 2D data with errors in and `x` and `y`, use specialized tools like `TGraphErrors::Fit()`, or build an explicit likelihood model if you want to stay with RooFit. +* The **RooStats::HybridPlot** class and the related **HybridResult::GetPlot** method are deprecated and will be removed in ROOT 6.42. + We kindly ask users to write their own ROOT-based plotting code, possibly based on the source code of the deprecated **HybridPlot** class, as pre-existing plot helpers are usually failing to be flexible enough for large-scale adoption. ## Removals @@ -66,9 +72,16 @@ The following people have contributed to this new version: multiGraph->Add(static_cast(gr->Clone())); } ``` +* The `compression_default` build option was removed. It was supposed to change the default compression algorithm, but didn't actually work with the default parameters of `TFile`. ## Build System +### Moving from builtin dependencies to system-provided packages + +* The general direction of the ROOT project is to become more and more reliant on system packages. It is *recommended* to make the packages required by ROOT available on the system, e.g. via a package manager, and not with the builtin mechanism. This allows for timely updates and reduces the size of the installed binaries. +* The previously vendored builtins `freetype`, `zlib`, `lzma`, `zstd`, `lz4`, `libpng`, `giflib`, `libjpeg`, and `openssl` should be installed in the system if possible. ROOT will not automatically fall-back to their builtin versions if these are not found: the user is informed of that with a helpful message. If installing these dependencies in the system is not possible, the CMake option `-Dbuiltin_XYZ=ON` has to be consciously chosen by the user. +* For the builtin versions of `freetype`, `zlib`, `lzma`, `zstd`, `lz4`, `libpng`, `giflib`, `libjpeg`, the source tarballs are now fetched from [SPI](https://spi.web.cern.ch)'s [website](https://lcgpackages.web.cern.ch/), as for the vast majority of ROOT's builtins, e.g. `openssl` or `xrootd`. + ## Core Libraries * ROOT now adds a RUNPATH to compiled macros. This ensures that when compiled macros are loaded, they load the libraries that belong to the ROOT installation @@ -231,6 +244,19 @@ This is new and efficient bracketing root-finding algorithm. It combines bisecti - The constructors of **RooDataSet** and **RooDataHist** that combine datasets via `Index()` and `Import()` now validate that the import names correspond to existing states of the index category. If an imported data slice refers to a category label that is not defined in the index category, the constructor now throws an error. Previously, such labels were silently added as new category states, which could lead to inconsistent datasets when the state names were not synchronized with the model definition. This change prevents the creation of invalid combined datasets and surfaces configuration problems earlier. +### Deprecation of the the constant term optimization for legacy test statistic classes + +The **RooFit::Optimize()** option (constant term optimization) has been deprecated and will be removed in ROOT 6.42. +This option only affects the `legacy` evaluation backend. + +**Important behavior change**: Constant term optimization is now disabled by default when using the legacy backend. +Previously, it was enabled by default. As a result, users who still rely on the legacy backend may observe *slower fits*. + +The default vectorized CPU evaluation backend (introduced in ROOT 6.32) already performs these optimizations automatically and is not affected by this change. +Users are strongly encouraged to switch to the vectorized CPU backend if they are still using the legacy backend. + +If the vectorized backend does not work for a given use case, **please report it by opening an issue on the ROOT GitHub repository**. + ### New implementation of `RooHistError::getPoissonInterval` **RooHistError::getPoissonInterval** was reimplemented to use an exact chi-square–based construction (Garwood interval) instead of asymptotic approximations and lookup tables. @@ -253,6 +279,14 @@ Now: Results may differ from previous ROOT versions for `n > 100` or `nSigma != 1`. The new implementation is statistically consistent and recommended. +### Removal of global expensive object caching in RooFit + +The global “expensive object cache” used in RooFit to store numeric integrals and intermediate histogram results has been removed. + +While originally intended as a performance optimization, this mechanism could lead to **incorrect results due to cache collisions**: cached integrals or histograms created in one context (e.g. during plotting) could be reused unintentionally in a different context, even when the underlying configuration had changed. + +Given the risk of silently incorrect physics results, and the absence of known workflows that depend critically on this feature, this global caching mechanism has been removed. If you encounter performance regressions in workflows involving expensive integrals or convolutions, we encourage you to report your use case and performance regression as a GitHub issue, so that targeted and robust optimizations can be developed, + ## RDataFrame - The message shown in ROOT 6.38 to inform users about change of default compression setting used by Snapshot (was 101 before 6.38, became 505 in 6.38) is now removed. @@ -369,6 +403,29 @@ after importing ROOT. This option is intended **for debugging only and will be removed in ROOT 6.44**. +### Drop support for calling C++ functions with non-const pointer references + +From now on, we disallow calling C++ functions with non-const pointer references (`T*&`) from Python. +These allow pointer rebinding, which cannot be represented safely in Python and could previously lead to confusing behavior. +A `TypeError` is now raised. Typical ROOT usage is unaffected. + +In the rare case where you want to call such a function, please change the C++ interface or - if the interface is outside your control - write a wrapper function that avoids non-const pointer references as arguments. + +For example, a function with the signature `bool setPtr(MyClass *&)` could be wrapped by a function that augments the return value with the updated pointer: +``` +ROOT.gInterpreter.Declare(""" + std::pair setPtrWrapper(MyClass *ptr) { + bool out = setPtr(ptr); + return {out, ptr}; + } +""") +``` +Then, call it from Python as follows: +```Python +# Use tuple unpacking for convenience +_, ptr = cppyy.gbl.setPtrWrapper(ptr) +``` + ### UHI #### Backwards incompatible changes - `TH1.values()` now returns a **read-only** NumPy array by default. Previously it returned a writable array that allowed modifying histogram contents implicitly. @@ -430,10 +487,18 @@ The version of the following packages has been updated: - cppzeromq: 4.10.0 - fftw3: 3.3.10 + - freetype: 2.14.3 - gsl: 2.8 - gtest: 1.17.0 + - giflib: 5.2.2 + - libjpeg-turbo 3.1.3 is now used as a replacement for libjpeg + - libpng: 1.6.4 - libzeromq: 4.3.5 - - xrootd: 5.9.1 + - lz4: 1.10.0 + - lzma: 5.8.2 + - xrootd: 5.9.2 + - zlib: 1.3.2 + - zstd: 1.5.7 ## Items addressed for this release diff --git a/bindings/distrdf/python/DistRDF/Backends/Base.py b/bindings/distrdf/python/DistRDF/Backends/Base.py index 6336b6f1cb928..e1762eafaac53 100644 --- a/bindings/distrdf/python/DistRDF/Backends/Base.py +++ b/bindings/distrdf/python/DistRDF/Backends/Base.py @@ -29,7 +29,7 @@ from ..Ranges import DataRange -def setup_mapper(initialization_fn: Callable, code_to_declare: str) -> None: +def setup_mapper(initialization_fn: Callable, code_to_declare: str) -> None: """ Perform initial setup steps common to every mapper function. """ @@ -46,14 +46,17 @@ def setup_mapper(initialization_fn: Callable, code_to_declare: str) -> None: # Run initialization method to prepare the worker runtime # environment initialization_fn() - + # Declare all user code in one call ROOT.gInterpreter.Declare(code_to_declare) -def get_mergeable_values(starting_node: ROOT.RDF.RNode, range_id: int, - computation_graph_callable: Callable[[ROOT.RDF.RNode, int], List], - exec_id: ExecutionIdentifier) -> List: +def get_mergeable_values( + starting_node: ROOT.RDF.RNode, + range_id: int, + computation_graph_callable: Callable[[ROOT.RDF.RNode, int], List], + exec_id: ExecutionIdentifier, +) -> List: """ Triggers the computation graph and returns a list of mergeable values. """ @@ -78,17 +81,18 @@ class TaskResult: for a tree opened in the task and the value is the number of entries in that tree. This attribute is not None only in a TTree-based run. """ + mergeables: Optional[List] entries_in_trees: Optional[Ranges.TaskTreeEntries] def distrdf_mapper( - current_range: Ranges.DataRange, - build_rdf_from_range: Callable[[Union[Ranges.EmptySourceRange, Ranges.TreeRangePerc]], - TaskObjects], - computation_graph_callable: Callable[[ROOT.RDF.RNode, int], List], - initialization_fn: Callable, - code_to_declare: str) -> TaskResult: + current_range: Ranges.DataRange, + build_rdf_from_range: Callable[[Union[Ranges.EmptySourceRange, Ranges.TreeRangePerc]], TaskObjects], + computation_graph_callable: Callable[[ROOT.RDF.RNode, int], List], + initialization_fn: Callable, + code_to_declare: str, +) -> TaskResult: """ Maps the computation graph to the input logical range of entries. """ @@ -96,13 +100,14 @@ def distrdf_mapper( # to better propagate exceptions. try: setup_mapper(initialization_fn, code_to_declare) - + # Build an RDataFrame instance for the current mapper task, based # on the type of the head node. rdf_plus = build_rdf_from_range(current_range) if rdf_plus.rdf is not None: - mergeables = get_mergeable_values(rdf_plus.rdf, current_range.id, computation_graph_callable, - current_range.exec_id) + mergeables = get_mergeable_values( + rdf_plus.rdf, current_range.id, computation_graph_callable, current_range.exec_id + ) else: mergeables = None except ROOT.std.exception as e: @@ -117,7 +122,6 @@ def merge_values(mergeables_out: Iterable, mergeables_in: Iterable) -> Iterable: first argument. """ if mergeables_out is not None and mergeables_in is not None: - for mergeable_out, mergeable_in in zip(mergeables_out, mergeables_in): Utils.merge_values(mergeable_out, mergeable_in) @@ -133,8 +137,7 @@ def merge_values(mergeables_out: Iterable, mergeables_in: Iterable) -> Iterable: return mergeables_out -def distrdf_reducer(results_inout: TaskResult, - results_in: TaskResult) -> TaskResult: +def distrdf_reducer(results_inout: TaskResult, results_in: TaskResult) -> TaskResult: """ Merges two given iterables of values that were returned by two mapper function executions. Returns the first argument with its values updated from @@ -176,7 +179,7 @@ class BaseBackend(ABC): shared_libraries (list): List of shared libraries needed for the analysis. """ - + initialization = staticmethod(lambda: None) headers = set() files = set() @@ -201,15 +204,17 @@ def register_initialization(cls, fun, *args, **kwargs): **kwargs (dict): Keyword arguments used to execute the function. """ cls.initialization = staticmethod(partial(fun, *args, **kwargs)) - fun(*args, **kwargs) + fun(*args, **kwargs) @classmethod - def register_declaration(cls, code_to_declare): - + def register_declaration(cls, code_to_declare): + stripped = code_to_declare.strip() sha256 = hashlib.sha256() sha256.update(stripped.encode()) hex = sha256.hexdigest() + # Ensure the hex does not start with a digit, which would be an invalid C++ identifier + hex = "ROOT_RDF_DISTRIBUTED_CODE_" + hex if cls.strings_to_declare.get(hex, None) is None: code_with_guard = f"#ifndef {hex}\n#define {hex}\n{stripped}\n#endif" cls.strings_to_declare[hex] = code_with_guard @@ -218,19 +223,19 @@ def register_declaration(cls, code_to_declare): @classmethod def register_shared_lib(cls, paths_to_shared_libraries): - + libraries_to_distribute, pcms_to_distribute = Utils.register_shared_libs(paths_to_shared_libraries) - + cls.shared_libraries.update(libraries_to_distribute) cls.pcms.update(pcms_to_distribute) - + @classmethod def register_headers(cls, paths_to_headers): - + headers_to_distribute = Utils.register_headers(paths_to_headers) cls.headers.update(headers_to_distribute) - - @classmethod + + @classmethod def register_files(cls, paths_to_files): """ Sends to the workers the generic files needed by the user. @@ -240,12 +245,15 @@ def register_files(cls, paths_to_files): distributed workers. """ files_to_distribute = Utils.register_files(paths_to_files) - cls.files.update(files_to_distribute) - + cls.files.update(files_to_distribute) + @abstractmethod - def ProcessAndMerge(self, ranges: List[DataRange], - mapper: Callable[..., TaskResult], - reducer: Callable[[TaskResult, TaskResult], TaskResult]) -> TaskResult: + def ProcessAndMerge( + self, + ranges: List[DataRange], + mapper: Callable[..., TaskResult], + reducer: Callable[[TaskResult, TaskResult], TaskResult], + ) -> TaskResult: """ Subclasses must define how to run map-reduce functions on a given backend. diff --git a/bindings/distrdf/python/DistRDF/Proxy.py b/bindings/distrdf/python/DistRDF/Proxy.py index 894da112eeb31..c1db4f6369daa 100644 --- a/bindings/distrdf/python/DistRDF/Proxy.py +++ b/bindings/distrdf/python/DistRDF/Proxy.py @@ -57,7 +57,8 @@ def execute_graph(node: Node) -> None: # the workers is contained in the head node node.get_head().execute_graph() -def _update_internal_df_with_transformation(node:Node, operation: Operation) -> None: + +def _update_internal_df_with_transformation(node: Node, operation: Operation) -> None: """Propagate transform operations to the headnode internal RDataFrame""" # The parent node is None only if the node is the head node parent_node = node.parent if node.parent is not None else node @@ -66,6 +67,7 @@ def _update_internal_df_with_transformation(node:Node, operation: Operation) -> # Call and inject the result in the Python node node.rdf_node = rdf_operation(*operation.args, **operation.kwargs) + def _create_new_node(parent: Node, operation: Operation.Operation) -> Node: """Creates a new node and inserts it in the computation graph""" @@ -144,8 +146,10 @@ def __getitem__(self, key: str): try: return self.proxied_node.value.GetVariation(key) except ROOT.std.runtime_error as e: - raise KeyError(f"'{key}' is not a valid variation name in this branch of the graph. " - f"Available variations are {self.GetKeys()}") from e + raise KeyError( + f"'{key}' is not a valid variation name in this branch of the graph. " + f"Available variations are {self.GetKeys()}" + ) from e def GetKeys(self) -> List[str]: """ @@ -160,13 +164,16 @@ def GetKeys(self) -> List[str]: # TODO: # The event loop has not been triggered yet. Currently we can't retrieve # the list of variation names without starting the distributed computations - raise RuntimeError(textwrap.dedent( - """ + raise RuntimeError( + textwrap.dedent( + """ A list of names of systematic variations was requested, but the corresponding map of variations is not present. The variation names cannot be retrieved unless the computation graph has properly run and finished. Something may have gone wrong in the distributed execution, or no variation values were explicitly requested. In the future, it will be possible to get the variation names without triggering. - """)) + """ + ) + ) else: if self._keys is None: self._keys = [str(key) for key in self.proxied_node.value.GetKeys()] @@ -245,20 +252,15 @@ def __getattr__(self, attr): return getattr(self.proxied_node, attr) except AttributeError: if self.proxied_node.operation: - msg = "'{0}' object has no attribute '{1}'".format( - str(self.proxied_node.operation.name), - attr - ) + msg = "'{0}' object has no attribute '{1}'".format(str(self.proxied_node.operation.name), attr) else: - msg = "'RDataFrame' object has no attribute '{}'".format( - attr - ) + msg = "'RDataFrame' object has no attribute '{}'".format(attr) raise AttributeError(msg) def GetColumnNames(self): """Forward call to the internal RDataFrame object""" return self.proxied_node.rdf_node.GetColumnNames() - + def GetColumnType(self, column): """Forward call to the internal RDataFrame object""" return self.proxied_node.rdf_node.GetColumnType(column) @@ -275,7 +277,7 @@ def _create_new_op(self, *args, **kwargs): @singledispatch def get_proxy_for(operation: Operation.Transformation, node: Node) -> NodeProxy: - """"Returns appropriate proxy for the input node""" + """ "Returns appropriate proxy for the input node""" _update_internal_df_with_transformation(node, operation) return NodeProxy(node) @@ -295,6 +297,12 @@ def _(operation: Operation.InstantAction, node: Node) -> Any: def _(operation: Operation.Snapshot, node: Node) -> Union[ResultPtrProxy, Any]: if len(operation.args) == 4: # An RSnapshotOptions instance was passed as fourth argument + + if str(operation.args[3].fMode).lower() == "update": + # UPDATE mode is not supported since it would required synchronised access to the same file from the + # distributed workers + raise ValueError("Opening a file in UPDATE mode is not supported in distributed Snapshot.") + if operation.args[3].fLazy: return get_proxy_for.dispatch(Operation.Action)(operation, node) diff --git a/bindings/pyroot/cppyy/CPyCppyy/CMakeLists.txt b/bindings/pyroot/cppyy/CPyCppyy/CMakeLists.txt index 065a89348ff4a..c21fb317f8cb6 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/CMakeLists.txt +++ b/bindings/pyroot/cppyy/CPyCppyy/CMakeLists.txt @@ -7,7 +7,6 @@ set(headers include/CPyCppyy/API.h include/CPyCppyy/Reflex.h - include/CPyCppyy/PyResult.h include/CPyCppyy/CommonDefs.h include/CPyCppyy/PyException.h include/CPyCppyy/DispatchPtr.h @@ -38,7 +37,6 @@ set(sources src/MemoryRegulator.cxx src/ProxyWrappers.cxx src/PyException.cxx - src/PyResult.cxx src/PyStrings.cxx src/Pythonize.cxx src/TemplateProxy.cxx diff --git a/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/API.h b/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/API.h index 0a4e4b3f6ab31..e619348e11c0d 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/API.h +++ b/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/API.h @@ -40,7 +40,6 @@ namespace Cppyy { } // namespace Cppyy // Bindings -#include "CPyCppyy/PyResult.h" #include "CPyCppyy/CommonDefs.h" // Standard @@ -174,6 +173,10 @@ CPYCPPYY_EXTERN void* CallVoidP(Cppyy::TCppMethod_t, Cppyy::TCppObject_t, CallCo //- C++ access to cppyy objects --------------------------------------------- +// Get C++ Instance (python object proxy) name. +// Sets a TypeError and returns an empty string if the pyobject is not a CPPInstance. +CPYCPPYY_EXTERN std::string Instance_GetScopedFinalName(PyObject* pyobject); + // C++ Instance (python object proxy) to void* conversion CPYCPPYY_EXTERN void* Instance_AsVoidPtr(PyObject* pyobject); @@ -189,6 +192,10 @@ CPYCPPYY_EXTERN bool Scope_CheckExact(PyObject* pyobject); CPYCPPYY_EXTERN bool Instance_Check(PyObject* pyobject); CPYCPPYY_EXTERN bool Instance_CheckExact(PyObject* pyobject); +// memory management: ownership of the underlying C++ object +CPYCPPYY_EXTERN void Instance_SetPythonOwns(PyObject* pyobject); +CPYCPPYY_EXTERN void Instance_SetCppOwns(PyObject* pyobject); + // type verifier for sequences CPYCPPYY_EXTERN bool Sequence_Check(PyObject* pyobject); @@ -199,6 +206,11 @@ CPYCPPYY_EXTERN bool Instance_IsLively(PyObject* pyobject); CPYCPPYY_EXTERN bool Overload_Check(PyObject* pyobject); CPYCPPYY_EXTERN bool Overload_CheckExact(PyObject* pyobject); +// Sets the __reduce__ method for the CPPInstance class, which is by default not +// implemented by cppyy but might make sense to implement by frameworks that +// support IO of arbitrary C++ objects, like ROOT. +CPYCPPYY_EXTERN void Instance_SetReduceMethod(PyCFunction reduceMethod); + //- access to the python interpreter ---------------------------------------- @@ -208,9 +220,6 @@ CPYCPPYY_EXTERN bool Import(const std::string& name); // execute a python statement (e.g. "import sys") CPYCPPYY_EXTERN bool Exec(const std::string& cmd); -// evaluate a python expression (e.g. "1+1") -CPYCPPYY_EXTERN const PyResult Eval(const std::string& expr); - // execute a python stand-alone script, with argv CLI arguments CPYCPPYY_EXTERN void ExecScript(const std::string& name, const std::vector& args); diff --git a/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/PyResult.h b/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/PyResult.h deleted file mode 100644 index 7e43dffc9fa09..0000000000000 --- a/bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/PyResult.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef CPYCPPYY_PYRESULT_H -#define CPYCPPYY_PYRESULT_H - -////////////////////////////////////////////////////////////////////////////// -// // -// TPyResult // -// // -// Morphing return type from evaluating python expressions. // -// // -////////////////////////////////////////////////////////////////////////////// - -// Python -struct _object; -typedef _object PyObject; - -// Bindings -#include "CPyCppyy/CommonDefs.h" - - -namespace CPyCppyy { - -class CPYCPPYY_CLASS_EXTERN PyResult { -public: - PyResult(); - PyResult(PyObject* pyobject); - PyResult(const PyResult&); - PyResult& operator=(const PyResult&); - virtual ~PyResult(); - -// conversions to standard types, may fail if unconvertible - operator char*() const; - operator const char*() const; - operator char() const; - - operator long() const; - operator int() const { return (int)operator long(); } - operator short() const { return (short)operator long(); } - - operator unsigned long() const; - operator unsigned int() const { - return (unsigned int)operator unsigned long(); - } - operator unsigned short() const { - return (unsigned short)operator unsigned long(); - } - - operator double() const; - operator float() const { return (float)operator double(); } - -// used for both general object type and PyObject conversions - operator void*() const; - - template - operator T*() const { return (T*)(void*)*this; } - -// used strictly for PyObject conversions - operator PyObject*() const; - -private: - PyObject* fPyObject; /// - -// Bindings -#include "CPyCppyy/CommonDefs.h" - - -class CPYCPPYY_CLASS_EXTERN TPyArg { -public: -// converting constructors - TPyArg(PyObject*); - TPyArg(int); - TPyArg(long); - TPyArg(double); - TPyArg(const char*); - - TPyArg(const TPyArg&); - TPyArg& operator=(const TPyArg&); - virtual ~TPyArg(); - -// "extractor" - operator PyObject*() const; - -// constructor and generic dispatch - static void CallConstructor( - PyObject*& pyself, PyObject* pyclass, const std::vector& args); - static void CallConstructor(PyObject*& pyself, PyObject* pyclass); // default ctor - static PyObject* CallMethod(PyObject* pymeth, const std::vector& args); - static void CallDestructor( - PyObject*& pyself, PyObject* pymeth, const std::vector& args); - static void CallDestructor(PyObject*& pyself); - -private: - mutable PyObject* fPyObject; ///ObjectIsA(); + return Cppyy::GetScopedFinalName(pyobjectClass); +} + +//----------------------------------------------------------------------------- void* CPyCppyy::Instance_AsVoidPtr(PyObject* pyobject) { // Extract the object pointer held by the CPPInstance pyobject. @@ -184,6 +196,32 @@ bool CPyCppyy::Instance_CheckExact(PyObject* pyobject) return CPPInstance_CheckExact(pyobject); } +//----------------------------------------------------------------------------- +void CPyCppyy::Instance_SetPythonOwns(PyObject* pyobject) +{ + if (!Initialize()) + return; + +// check validity of cast + if (!CPPInstance_Check(pyobject)) + return; + + ((CPPInstance *)pyobject)->PythonOwns(); +} + +//----------------------------------------------------------------------------- +void CPyCppyy::Instance_SetCppOwns(PyObject* pyobject) +{ + if (!Initialize()) + return; + +// check validity of cast + if (!CPPInstance_Check(pyobject)) + return; + + ((CPPInstance *)pyobject)->CppOwns(); +} + //----------------------------------------------------------------------------- bool CPyCppyy::Sequence_Check(PyObject* pyobject) { @@ -254,6 +292,11 @@ bool CPyCppyy::Overload_CheckExact(PyObject* pyobject) return CPPOverload_CheckExact(pyobject); } +//----------------------------------------------------------------------------- +void CPyCppyy::Instance_SetReduceMethod(PyCFunction reduceMethod) +{ + CPPInstance::ReduceMethod() = reduceMethod; +} //- access to the python interpreter ---------------------------------------- bool CPyCppyy::Import(const std::string& mod_name) @@ -296,10 +339,6 @@ bool CPyCppyy::Import(const std::string& mod_name) fullname += "."; fullname += CPyCppyy_PyText_AsString(pyClName); - // force class creation (this will eventually call TPyClassGenerator) - // TODO: the following is broken (and should live in Cppyy.cxx) to - // TClass::GetClass(fullname.c_str(), true); - Py_XDECREF(pyClName); } @@ -338,117 +377,58 @@ void CPyCppyy::ExecScript(const std::string& name, const std::vector("argv")); // borrowed - if (!oldargv) // e.g. apache + PyObject* oldargv = PySys_GetObject("argv"); // borrowed + if (oldargv) { + PyObject* copy = PyList_GetSlice(oldargv, 0, PyList_Size(oldargv)); + oldargv = copy; // now owned + } else { PyErr_Clear(); - else { - PyObject* l = PyList_New(PyList_GET_SIZE(oldargv)); - for (int i = 0; i < PyList_GET_SIZE(oldargv); ++i) { - PyObject* item = PyList_GET_ITEM(oldargv, i); - Py_INCREF(item); - PyList_SET_ITEM(l, i, item); // steals ref - } - oldargv = l; } -// create and set (add program name) the new command line - int argc = args.size() + 1; -#if PY_VERSION_HEX < 0x03000000 -// This is a legacy implementation for Python 2 - const char** argv = new const char*[argc]; - for (int i = 1; i < argc; ++i) argv[i] = args[i-1].c_str(); - argv[0] = Py_GetProgramName(); - PySys_SetArgv(argc, const_cast(argv)); - delete [] argv; -#else -// This is a common code block for Python 3. We prefer using objects to -// automatize memory management and not introduce even more preprocessor -// branching for deletion at the end of the method. -// -// FUTURE IMPROVEMENT ONCE OLD PYTHON VERSIONS ARE NOT SUPPORTED BY CPPYY: -// Right now we use C++ objects to automatize memory management. One could use -// RAAI and the Python memory allocation API (PEP 445) once some old Python -// version is deprecated in CPPYY. That new feature is available since version -// 3.4 and the preprocessor branching to also support that would be so -// complicated to make the code unreadable. - std::vector argv2; - argv2.reserve(argc); - argv2.emplace_back(name.c_str(), &name[name.size()]); - - for (int i = 1; i < argc; ++i) { - auto iarg = args[i - 1].c_str(); - argv2.emplace_back(iarg, &iarg[strlen(iarg)]); - } - -#if PY_VERSION_HEX < 0x03080000 -// Before version 3.8, the code is one simple line - wchar_t *argv2_arr[argc]; - for (int i = 0; i < argc; ++i) { - argv2_arr[i] = const_cast(argv2[i].c_str()); - } - PySys_SetArgv(argc, argv2_arr); +// build new argv + const int argc = (int)args.size() + 1; + std::vector wargv(argc); -#else -// Here we comply to "PEP 587 – Python Initialization Configuration" to avoid -// deprecation warnings at compile time. - class PyConfigHelperRAAI { - public: - PyConfigHelperRAAI(const std::vector &argv2) - { - PyConfig_InitPythonConfig(&fConfig); - fConfig.parse_argv = 1; - UpdateArgv(argv2); - InitFromConfig(); - } - ~PyConfigHelperRAAI() { PyConfig_Clear(&fConfig); } - - private: - void InitFromConfig() { Py_InitializeFromConfig(&fConfig); }; - void UpdateArgv(const std::vector &argv2) - { - auto WideStringListAppendHelper = [](PyWideStringList *wslist, const wchar_t *wcstr) { - PyStatus append_status = PyWideStringList_Append(wslist, wcstr); - if (PyStatus_IsError(append_status)) { - std::wcerr << "Error: could not append element " << wcstr << " to arglist - " << append_status.err_msg - << std::endl; - } - }; - -#if PY_VERSION_HEX < 0x30d00f0 - WideStringListAppendHelper(&fConfig.argv, Py_GetProgramName()); -#else - PyObject* progname = PySys_GetObject("executable"); // borrowed - wchar_t buf[4096]; - Py_ssize_t sz = CPyCppyy_PyUnicode_AsWideChar(progname, buf, 4095); - if (0 < sz) - WideStringListAppendHelper(&fConfig.argv, buf); -#endif - for (const auto &iarg : argv2) { - WideStringListAppendHelper(&fConfig.argv, iarg.c_str()); - } - } - PyConfig fConfig; - }; + wargv[0] = Py_DecodeLocale(name.c_str(), nullptr); - PyConfigHelperRAAI pych(argv2); + for (int i = 1; i < argc; ++i) { + wargv[i] = Py_DecodeLocale(args[i - 1].c_str(), nullptr); + } -#endif // of the else branch of PY_VERSION_HEX < 0x03080000 -#endif // of the else branch of PY_VERSION_HEX < 0x03000000 +// set sys.argv + PyObject* sysmod = PyImport_ImportModule("sys"); // new reference + if (sysmod) { + PyObject* argv_obj = PyList_New(argc); + for (int i = 0; i < argc; ++i) { + PyList_SET_ITEM(argv_obj, i, PyUnicode_FromWideChar(wargv[i], -1)); + } + PyObject_SetAttrString(sysmod, "argv", argv_obj); + Py_DECREF(argv_obj); + Py_DECREF(sysmod); + } else { + PyErr_Print(); + } // actual script execution PyObject* gbl = PyDict_Copy(gMainDict); PyObject* result = // PyRun_FileEx closes fp (b/c of last argument "1") PyRun_FileEx(fp, const_cast(name.c_str()), Py_file_input, gbl, gbl, 1); + if (!result) PyErr_Print(); + Py_XDECREF(result); Py_DECREF(gbl); // restore original command line if (oldargv) { - PySys_SetObject(const_cast("argv"), oldargv); + PySys_SetObject("argv", oldargv); Py_DECREF(oldargv); } + +// free memory from Py_DecodeLocale + for (auto ptr : wargv) + PyMem_RawFree(ptr); } //----------------------------------------------------------------------------- @@ -472,61 +452,6 @@ bool CPyCppyy::Exec(const std::string& cmd) return false; } -//----------------------------------------------------------------------------- -const CPyCppyy::PyResult CPyCppyy::Eval(const std::string& expr) -{ -// Evaluate a python expression. -// -// Caution: do not hold on to the return value: either store it in a builtin -// type (implicit casting will work), or in a pointer to a cppyy object (explicit -// casting to a void* is required). - if (!Initialize()) - return PyResult(); - -// evaluate the expression - PyObject* result = - PyRun_String(const_cast(expr.c_str()), Py_eval_input, gMainDict, gMainDict); - -// report errors as appropriate; return void - if (!result) { - PyErr_Print(); - return PyResult(); - } - -// results that require no conversion - if (result == Py_None || CPPInstance_Check(result) || - PyBytes_Check(result) || - PyFloat_Check(result) || PyLong_Check(result) || PyInt_Check(result)) - return PyResult(result); - -// explicit conversion for python type required - PyObject* pyclass = (PyObject*)Py_TYPE(result); - -// retrieve class name and the module in which it resides - PyObject* name = PyObject_GetAttr(pyclass, PyStrings::gName); - PyObject* module = PyObject_GetAttr(pyclass, PyStrings::gModule); - - // concat name - std::string qname = - std::string(CPyCppyy_PyText_AsString(module)) + \ - '.' + CPyCppyy_PyText_AsString(name); - Py_DECREF(module); - Py_DECREF(name); - -// locate cppyy style class with this name - // TODO: use Cppyy.cxx ... - //TClass* klass = TClass::GetClass(qname.c_str()); - void* klass = nullptr; - -// construct general cppyy python object that pretends to be of class 'klass' - if (klass) - return PyResult(result); - -// no conversion, return null pointer object - Py_DECREF(result); - return PyResult(); -} - //----------------------------------------------------------------------------- void CPyCppyy::Prompt() { // Enter an interactive python session (exit with ^D). State is preserved diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx index 301e9d39d260e..57095383c3e7b 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx @@ -400,19 +400,19 @@ static PySequenceMethods op_as_sequence = { 0, // sq_inplace_repeat }; -std::function &CPPInstance::ReduceMethod() { - static std::function reducer; +PyCFunction &CPPInstance::ReduceMethod() { + static PyCFunction reducer = nullptr; return reducer; } -PyObject *op_reduce(PyObject *self, PyObject * /*args*/) +PyObject *op_reduce(PyObject *self, PyObject * args) { auto &reducer = CPPInstance::ReduceMethod(); if (!reducer) { PyErr_SetString(PyExc_NotImplementedError, ""); return nullptr; } - return reducer(self); + return reducer(self, args); } diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.h b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.h index fcb0ad3d5d11a..e657999327c11 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.h @@ -10,12 +10,13 @@ ////////////////////////////////////////////////////////////////////////////// // Bindings +#ifndef Py_LIMITED_API #include "CPPScope.h" +#endif #include "Cppyy.h" #include "CallContext.h" // for Parameter // Standard -#include #include #include @@ -87,7 +88,7 @@ class CPPInstance { // implementation of the __reduce__ method: doesn't wrap any function by // default but can be re-assigned by libraries that add C++ object // serialization support, like ROOT - static std::function &ReduceMethod(); + static PyCFunction &ReduceMethod(); private: void CreateExtension(); @@ -117,12 +118,14 @@ inline void* CPPInstance::GetObject() } //---------------------------------------------------------------------------- +#ifndef Py_LIMITED_API inline Cppyy::TCppType_t CPPInstance::ObjectIsA(bool check_smart) const { // Retrieve the C++ type identifier (or raw type if smart). if (check_smart || !IsSmart()) return ((CPPClass*)Py_TYPE(this))->fCppType; return GetSmartIsA(); } +#endif //- object proxy type and type verification ---------------------------------- @@ -133,6 +136,7 @@ extern __declspec(dllimport) PyTypeObject CPPInstance_Type; extern PyTypeObject CPPInstance_Type; #endif +#ifndef Py_LIMITED_API template inline bool CPPInstance_Check(T* object) { @@ -142,6 +146,7 @@ inline bool CPPInstance_Check(T* object) (Py_TYPE(object)->tp_new == CPPInstance_Type.tp_new || \ PyObject_TypeCheck(object, &CPPInstance_Type)); } +#endif template inline bool CPPInstance_CheckExact(T* object) diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h index e3244bdcfe74b..84b193d7646a7 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h @@ -276,14 +276,6 @@ inline Py_ssize_t PyNumber_AsSsize_t(PyObject* obj, PyObject*) { #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #endif -#if PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03010000 -#define CPyCppyy_PyBuffer PyBuffer_Release -#else -inline void CPyCppyy_PyBuffer_Release(PyObject* /* unused */, Py_buffer* view) { - PyBuffer_Release(view); -} -#endif - // vector call support #if PY_VERSION_HEX >= 0x03090000 #define CPyCppyy_PyCFunction_Call PyObject_Call diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx index e4b53a2081637..80c27394f59a8 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx @@ -35,6 +35,12 @@ PyObject* Instance_FromVoidPtr( #include #include +#if PY_VERSION_HEX < 0x030b0000 +namespace CPyCppyy { +extern dict_lookup_func gDictLookupOrg; +dict_lookup_func gDictLookupOrg = nullptr; +} // namespace CPyCppyy +#endif // Note: as of py3.11, dictionary objects no longer carry a function pointer for // the lookup, so it can no longer be shimmed and "from cppyy.interactive import *" @@ -439,7 +445,8 @@ static PyObject* SetCppLazyLookup(PyObject*, PyObject* args) #else // As of py3.11, there is no longer a lookup function pointer in the dict object // to replace. Since this feature is not widely advertised, it's simply dropped - PyErr_Warn(PyExc_RuntimeWarning, (char*)"lazy lookup is no longer supported"); + if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)"lazy lookup is no longer supported", 1) < 0) + return nullptr; (void)args; // avoid warning about unused parameter #endif diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Converters.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/Converters.cxx index 56a569d8f0f26..cf7d27adc84db 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Converters.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Converters.cxx @@ -29,6 +29,9 @@ #include #include #include +#if __cplusplus >= 202002L +#include +#endif // codecvt does not exist for gcc4.8.5 and is in principle deprecated; it is // only used in py2 for char -> wchar_t conversion for std::wstring; if not @@ -441,8 +444,21 @@ static inline PY_LONG_LONG CPyCppyy_PyLong_AsStrictLongLong(PyObject* pyobject) static inline bool CArraySetArg( PyObject* pyobject, CPyCppyy::Parameter& para, char tc, int size, bool check=true) { +// Case of LowLevelView. In general, they also implement the buffer protocol, +// but for views around nullptr or C-style arrays without size info the buffer +// protocol implementation is incomplete and PyObject_GetBuffer will fail. + if (CPyCppyy::LowLevelView_Check(pyobject)) { + auto llview = ((CPyCppyy::LowLevelView*)pyobject); + if (llview->fBufInfo.itemsize != size || !strchr(llview->fBufInfo.format, tc)) { + PyErr_Format(PyExc_TypeError, + "could not convert argument to buffer or nullptr"); + return false; + } + + para.fValue.fVoidp = llview->get_buf(); + } // general case of loading a C array pointer (void* + type code) as function argument - if (pyobject == CPyCppyy::gNullPtrObject || pyobject == CPyCppyy::gDefaultObject) + else if (pyobject == CPyCppyy::gNullPtrObject || pyobject == CPyCppyy::gDefaultObject) para.fValue.fVoidp = nullptr; else { Py_ssize_t buflen = CPyCppyy::Utility::GetBuffer(pyobject, tc, size, para.fValue.fVoidp, check); @@ -1301,7 +1317,8 @@ bool CPyCppyy::CStringConverter::SetArg( // verify (too long string will cause truncation, no crash) if (fMaxSize != std::string::npos && fMaxSize < fBuffer.size()) - PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)"); + if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)", 1) < 0) + return false; if (!ctxt->fPyContext) { // use internal buffer as workaround @@ -1346,7 +1363,8 @@ bool CPyCppyy::CStringConverter::ToMemory(PyObject* value, void* address, PyObje // verify (too long string will cause truncation, no crash) if (fMaxSize != std::string::npos && fMaxSize < (std::string::size_type)len) - PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)"); + if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)"string too long for char array (truncated)", 1) < 0) + return false; // if address is available, and it wasn't set by this converter, assume a byte-wise copy; // otherwise assume a pointer copy (this relies on the converter to be used for properties, @@ -1423,7 +1441,8 @@ bool CPyCppyy::WCStringConverter::ToMemory(PyObject* value, void* address, PyObj // verify (too long string will cause truncation, no crash) if (fMaxSize != std::wstring::npos && fMaxSize < (std::wstring::size_type)len) - PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for wchar_t array (truncated)"); + if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)"string too long for wchar_t array (truncated)", 1) < 0) + return false; Py_ssize_t res = -1; if (fMaxSize != std::wstring::npos) @@ -1482,7 +1501,10 @@ bool CPyCppyy::name##Converter::ToMemory(PyObject* value, void* address, PyObjec \ /* verify (too long string will cause truncation, no crash) */ \ if (fMaxSize != std::wstring::npos && maxbytes < len) { \ - PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for "#type" array (truncated)");\ + if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)"string too long for "#type" array (truncated)", 1) < 0) { \ + Py_DECREF(bstr); \ + return false; \ + } \ len = maxbytes; \ } \ \ @@ -1645,6 +1667,78 @@ bool CPyCppyy::VoidArrayConverter::ToMemory(PyObject* value, void* address, PyOb return true; } +#if __cplusplus >= 202002L + +namespace CPyCppyy { + +class StdSpanConverter : public InstanceConverter { +public: + StdSpanConverter(std::string const &typeName, Cppyy::TCppType_t klass, bool keepControl = false) + : InstanceConverter{klass, keepControl}, fTypeName{typeName} + { + } + + ~StdSpanConverter() + { + if (fHasBuffer) { + PyBuffer_Release(&fBufinfo); + } + } + + bool SetArg(PyObject *, Parameter &, CallContext * = nullptr) override; + bool HasState() override { return true; } + +private: + std::string fTypeName; + std::span fBuffer; + bool fHasBuffer = false; + Py_buffer fBufinfo; +}; + +} // namespace CPyCppyy + +//---------------------------------------------------------------------------- +bool CPyCppyy::StdSpanConverter::SetArg(PyObject *pyobject, Parameter ¶, CallContext *ctxt) +{ + auto typecodeFound = Utility::TypecodeMap().find(fTypeName); + +// attempt to get buffer if the C++ type maps to a buffer type + if (typecodeFound == Utility::TypecodeMap().end() || !PyObject_CheckBuffer(pyobject)) { + // Fall back to regular InstanceConverter + return this->InstanceConverter::SetArg(pyobject, para, ctxt); + } + + Py_ssize_t buflen = 0; + char typecode = typecodeFound->second; + memset(&fBufinfo, 0, sizeof(Py_buffer)); + + if (PyObject_GetBuffer(pyobject, &fBufinfo, PyBUF_FORMAT) == 0) { + if (!strchr(fBufinfo.format, typecode)) { + PyErr_Format(PyExc_TypeError, + "buffer has incompatible type: expected '%c' for C++ type '%s', but got format '%s'", typecode, + fTypeName.c_str(), fBufinfo.format ? fBufinfo.format : ""); + PyBuffer_Release(&fBufinfo); + return false; + } + buflen = Utility::GetBuffer(pyobject, typecode, 1, para.fValue.fVoidp, false); + } + +// ok if buffer exists (can't perform any useful size checks) + if (para.fValue.fVoidp && buflen != 0) { + // We assume the layout for any std::span is the same, and just use + // std::span as a placeholder. Not elegant, but works. + fBuffer = std::span{(std::size_t *)para.fValue.fVoidp, static_cast(buflen)}; + fHasBuffer = true; + para.fValue.fVoidp = &fBuffer; + para.fTypeCode = 'V'; + return true; + } + + return false; +} + +#endif // __cplusplus >= 202002L + namespace { // Copy a buffer to memory address with an array converter. @@ -3187,11 +3281,25 @@ bool CPyCppyy::InitializerListConverter::SetArg( #endif } +namespace CPyCppyy { + +// raising converter to take out overloads +class NotImplementedConverter : public Converter { +public: + NotImplementedConverter(PyObject *errorType, std::string const &message) : fErrorType{errorType}, fMessage{message} {} + bool SetArg(PyObject*, Parameter&, CallContext* = nullptr) override; +private: + PyObject *fErrorType; + std::string fMessage; +}; + +} // namespace CPyCppyy + //---------------------------------------------------------------------------- bool CPyCppyy::NotImplementedConverter::SetArg(PyObject*, Parameter&, CallContext*) { // raise a NotImplemented exception to take a method out of overload resolution - PyErr_SetString(PyExc_NotImplementedError, "this method cannot (yet) be called"); + PyErr_SetString(fErrorType, fMessage.c_str()); return false; } @@ -3257,6 +3365,14 @@ CPyCppyy::Converter* CPyCppyy::CreateConverter(const std::string& fullType, cdim const std::string& cpd = TypeManip::compound(resolvedType); std::string realType = TypeManip::clean_type(resolvedType, false, true); +// mutable pointer references (T*&) are incompatible with Python's object model + if (cpd == "*&") { + return new NotImplementedConverter{PyExc_TypeError, + "argument type '" + resolvedType + "' is not supported: non-const references to pointers (T*&) allow a" + " function to replace the pointer itself. Python cannot represent this safely. Consider changing the" + " C++ API to return the new pointer or use a wrapper"}; + } + // accept unqualified type (as python does not know about qualifiers) h = gConvFactories.find((isConst ? "const " : "") + realType + cpd); if (h != gConvFactories.end()) @@ -3342,6 +3458,30 @@ CPyCppyy::Converter* CPyCppyy::CreateConverter(const std::string& fullType, cdim } } +#if __cplusplus >= 202002L +//-- special case: std::span + pos = resolvedType.find("span<"); + if (pos == 0 /* no std:: */ || pos == 5 /* with std:: */ || + pos == 6 /* const no std:: */ || pos == 11 /* const with std:: */ ) { + + auto pos1 = realType.find('<'); + auto pos21 = realType.find(','); // for the case there are more template args + auto pos22 = realType.find('>'); + auto len = std::min(pos21 - pos1, pos22 - pos1) - 1; + std::string value_type = realType.substr(pos1+1, len); + + // strip leading "const " + const std::string cprefix = "const "; + if (value_type.compare(0, cprefix.size(), cprefix) == 0) { + value_type = value_type.substr(cprefix.size()); + } + + std::string span_type = "std::span<" + value_type + ">"; + + return new StdSpanConverter{value_type, Cppyy::GetScope(span_type)}; + } +#endif + // converters for known C++ classes and default (void*) Converter* result = nullptr; if (Cppyy::TCppScope_t klass = Cppyy::GetScope(realType)) { @@ -3382,7 +3522,7 @@ CPyCppyy::Converter* CPyCppyy::CreateConverter(const std::string& fullType, cdim if (h != gConvFactories.end()) return (h->second)(dims); // else, unhandled moves - result = new NotImplementedConverter(); + result = new NotImplementedConverter{PyExc_NotImplementedError, "this method cannot (yet) be called"}; } if (!result && h != gConvFactories.end()) @@ -3395,7 +3535,8 @@ CPyCppyy::Converter* CPyCppyy::CreateConverter(const std::string& fullType, cdim else if (!cpd.empty()) result = new VoidArrayConverter(); // "user knows best" else - result = new NotImplementedConverter(); // fails on use + // fails on use + result = new NotImplementedConverter{PyExc_NotImplementedError, "this method cannot (yet) be called"}; } return result; diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Cppyy.h b/bindings/pyroot/cppyy/CPyCppyy/src/Cppyy.h index cc1340033bbaf..436d47fafe43f 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Cppyy.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Cppyy.h @@ -139,6 +139,8 @@ namespace Cppyy { CPPYY_IMPORT bool IsAggregate(TCppType_t type); CPPYY_IMPORT + bool IsIntegerType(const std::string &type_name); + CPPYY_IMPORT bool IsDefaultConstructable(TCppType_t type); CPPYY_IMPORT diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/DeclareConverters.h b/bindings/pyroot/cppyy/CPyCppyy/src/DeclareConverters.h index a390822d811ef..3f8ed377d3bd5 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/DeclareConverters.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/DeclareConverters.h @@ -481,13 +481,6 @@ class InitializerListConverter : public InstanceConverter { size_t fValueSize; }; - -// raising converter to take out overloads -class NotImplementedConverter : public Converter { -public: - bool SetArg(PyObject*, Parameter&, CallContext* = nullptr) override; -}; - } // unnamed namespace } // namespace CPyCppyy diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/DeclareExecutors.h b/bindings/pyroot/cppyy/CPyCppyy/src/DeclareExecutors.h index 888f63be96e63..ebb62c8f73d22 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/DeclareExecutors.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/DeclareExecutors.h @@ -76,6 +76,7 @@ CPPYY_ARRAY_DECL_EXEC(LLong); CPPYY_ARRAY_DECL_EXEC(ULLong); CPPYY_ARRAY_DECL_EXEC(Float); CPPYY_ARRAY_DECL_EXEC(Double); +CPPYY_ARRAY_DECL_EXEC(LDouble); CPPYY_ARRAY_DECL_EXEC(ComplexF); CPPYY_ARRAY_DECL_EXEC(ComplexD); CPPYY_ARRAY_DECL_EXEC(ComplexI); diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Dimensions.h b/bindings/pyroot/cppyy/CPyCppyy/src/Dimensions.h index 6a925033edb1d..c1bdc600eb3c2 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Dimensions.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Dimensions.h @@ -1,6 +1,9 @@ #ifndef CPYCPPYY_DIMENSIONS_H #define CPYCPPYY_DIMENSIONS_H +// Bindings +#include "CPyCppyy/CommonDefs.h" + // Standard #include #include diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Dispatcher.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/Dispatcher.cxx index b5f8eb38aed00..63bd3b9e7dc0e 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Dispatcher.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Dispatcher.cxx @@ -203,7 +203,8 @@ bool CPyCppyy::InsertDispatcher(CPPScope* klass, PyObject* bases, PyObject* dct, if (!Cppyy::HasVirtualDestructor(basetype)) { const std::string& bname = Cppyy::GetScopedFinalName(basetype); - PyErr_Warn(PyExc_RuntimeWarning, (char*)("class \""+bname+"\" has no virtual destructor").c_str()); + if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)("class \""+bname+"\" has no virtual destructor").c_str(), 1) < 0) + return false; } base_infos.emplace_back( diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Executors.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/Executors.cxx index fa0aefa0931fa..8a3648fad8576 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Executors.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Executors.cxx @@ -523,6 +523,7 @@ CPPYY_IMPL_ARRAY_EXEC(LLong, long long, ) CPPYY_IMPL_ARRAY_EXEC(ULLong, unsigned long long, ) CPPYY_IMPL_ARRAY_EXEC(Float, float, ) CPPYY_IMPL_ARRAY_EXEC(Double, double, ) +CPPYY_IMPL_ARRAY_EXEC(LDouble, long double, ) CPPYY_IMPL_ARRAY_EXEC(ComplexF, std::complex, ) CPPYY_IMPL_ARRAY_EXEC(ComplexD, std::complex, ) CPPYY_IMPL_ARRAY_EXEC(ComplexI, std::complex, ) @@ -1037,6 +1038,7 @@ struct InitExecFactories_t { gf["unsigned long long ptr"] = (ef_t)+[](cdims_t d) { return new ULLongArrayExecutor{d}; }; gf["float ptr"] = (ef_t)+[](cdims_t d) { return new FloatArrayExecutor{d}; }; gf["double ptr"] = (ef_t)+[](cdims_t d) { return new DoubleArrayExecutor{d}; }; + gf["long double ptr"] = (ef_t)+[](cdims_t d) { return new LDoubleArrayExecutor{d}; }; gf["std::complex ptr"] = (ef_t)+[](cdims_t d) { return new ComplexFArrayExecutor{d}; }; gf["std::complex ptr"] = (ef_t)+[](cdims_t d) { return new ComplexDArrayExecutor{d}; }; gf["std::complex ptr"] = (ef_t)+[](cdims_t d) { return new ComplexIArrayExecutor{d}; }; diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/LowLevelViews.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/LowLevelViews.cxx index 5a4314b1002c2..c71df38b71223 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/LowLevelViews.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/LowLevelViews.cxx @@ -565,7 +565,7 @@ static int ll_ass_sub(CPyCppyy::LowLevelView* self, PyObject* key, PyObject* val // rvalue must be an exporter if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0) { - if (src.obj) CPyCppyy_PyBuffer_Release(value, &src); + if (src.obj) PyBuffer_Release(&src); return ret; } @@ -581,7 +581,7 @@ static int ll_ass_sub(CPyCppyy::LowLevelView* self, PyObject* key, PyObject* val dest.len = dest.shape[0] * dest.itemsize; ret = copy_single(&dest, &src); - CPyCppyy_PyBuffer_Release(value, &src); + PyBuffer_Release(&src); return ret; } diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/PyResult.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/PyResult.cxx deleted file mode 100644 index 08775bd0dfa70..0000000000000 --- a/bindings/pyroot/cppyy/CPyCppyy/src/PyResult.cxx +++ /dev/null @@ -1,166 +0,0 @@ -// Bindings -#include "CPyCppyy.h" -#define CPYCPPYY_INTERNAL 1 -#include "CPyCppyy/PyResult.h" -#undef CPYCPPYY_INTERNAL - -#include "CPPInstance.h" - -// Standard -#include - - -//______________________________________________________________________________ -// Python expression eval result -// ============================= -// -// Transport class for bringing objects from python (dynamically typed) to Cling -// (statically typed). It is best to immediately cast a PyResult to the real -// type, either implicitly (for builtin types) or explicitly (through a void* -// cast for pointers to C++ objects). - - -//- constructors/destructor -------------------------------------------------- -CPyCppyy::PyResult::PyResult() -{ -// Construct a PyResult object from Py_None. - Py_INCREF(Py_None); - fPyObject = Py_None; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::PyResult(PyObject* pyobject) -{ -// Construct a PyResult from a python object. The python object may represent -// a C++ object. Steals reference to given python object. - if (!pyobject) { - Py_INCREF(Py_None); - fPyObject = Py_None; - } else - fPyObject = pyobject; // steals reference -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::PyResult(const PyResult& other) -{ -// Copy constructor. Applies python object reference counting. - Py_INCREF(other.fPyObject); - fPyObject = other.fPyObject; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult& CPyCppyy::PyResult::operator=(const PyResult& other) -{ -// Assignment operator. Applies python object reference counting. - if (this != &other) { - Py_INCREF(other.fPyObject); - Py_DECREF(fPyObject); - fPyObject = other.fPyObject; - } - - return *this; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::~PyResult() -{ -// Destructor. Reference counting for the held python object is in effect. - Py_DECREF(fPyObject); -} - - -//- public members ----------------------------------------------------------- -CPyCppyy::PyResult::operator char*() const -{ -// Cast python return value to C-style string (may fail). - return (char*)((const char*)*this); -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator const char*() const -{ -// Cast python return value to C-style string (may fail). - if (fPyObject == Py_None) // for void returns - return nullptr; - - const char* s = CPyCppyy_PyText_AsString(fPyObject); - if (PyErr_Occurred()) { - PyErr_Print(); - return nullptr; - } - - return s; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator char() const -{ -// Cast python return value to C++ char (may fail). - std::string s = operator const char*(); - if (s.size()) - return s[0]; - - return '\0'; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator long() const -{ -// Cast python return value to C++ long (may fail). - long l = PyLong_AsLong(fPyObject); - - if (PyErr_Occurred()) - PyErr_Print(); - - return l; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator unsigned long() const -{ -// Cast python return value to C++ unsigned long (may fail). - unsigned long ul = PyLong_AsUnsignedLong(fPyObject); - - if (PyErr_Occurred()) - PyErr_Print(); - - return ul; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator double() const -{ -// Cast python return value to C++ double (may fail). - double d = PyFloat_AsDouble(fPyObject); - - if (PyErr_Occurred()) - PyErr_Print(); - - return d; -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator void*() const -{ -// Cast python return value to C++ object with dictionary (may fail; note that -// you have to use the void* converter, as Cling will not call any other). - if (fPyObject == Py_None) - return nullptr; - - if (CPyCppyy::CPPInstance_Check(fPyObject)) { - ((CPyCppyy::CPPInstance*)fPyObject)->CppOwns(); - return ((CPyCppyy::CPPInstance*)fPyObject)->GetObject(); - } else - return fPyObject; // borrows reference -} - -//---------------------------------------------------------------------------- -CPyCppyy::PyResult::operator PyObject*() const -{ -// Direct return of the held PyObject; note the new reference. - if (fPyObject == Py_None) - return nullptr; - - Py_INCREF(fPyObject); - return fPyObject; -} diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Pythonize.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/Pythonize.cxx index 6f2a172fe2985..a0494ee3ad7f2 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Pythonize.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Pythonize.cxx @@ -52,6 +52,19 @@ bool HasAttrDirect(PyObject* pyclass, PyObject* pyname, bool mustBeCPyCppyy = fa return false; } +bool HasAttrInMRO(PyObject *pyclass, PyObject *pyname) +{ + // Check base classes in the MRO (skipping the class itself) for a CPyCppyy overload. + PyObject *mro = ((PyTypeObject *)pyclass)->tp_mro; + if (mro && PyTuple_Check(mro)) { + for (Py_ssize_t i = 1; i < PyTuple_GET_SIZE(mro); ++i) { + if (HasAttrDirect(PyTuple_GET_ITEM(mro, i), pyname, /*mustBeCPyCppyy=*/true)) + return true; + } + } + return false; +} + PyObject* GetAttrDirect(PyObject* pyclass, PyObject* pyname) { // get an attribute without causing getattr lookups PyObject* dct = PyObject_GetAttr(pyclass, PyStrings::gDict); @@ -1755,12 +1768,36 @@ bool CPyCppyy::Pythonize(PyObject* pyclass, const std::string& name) Utility::AddToClass(pyclass, pybool_name, (PyCFunction)NullCheckBool, METH_NOARGS); } -// for STL containers, and user classes modeled after them -// the attribute must be a CPyCppyy overload, otherwise the check gives false -// positives in the case where the class has a non-function attribute that is -// called "size". - if (HasAttrDirect(pyclass, PyStrings::gSize, /*mustBeCPyCppyy=*/ true)) { - Utility::AddToClass(pyclass, "__len__", "size"); + // for STL containers, and user classes modeled after them. Guard the alias to + // __len__ by verifying that size() returns an integer type and the class has + // begin()/end() or operator[] (i.e. is container-like). This prevents bool() + // returning False for valid objects whose size() returns non-integer types like + // std::optional. Skip if size() has multiple overloads, as that + // indicates it is not the simple container-style size() one would map to __len__. + if (HasAttrDirect(pyclass, PyStrings::gSize, /*mustBeCPyCppyy=*/true) || HasAttrInMRO(pyclass, PyStrings::gSize)) { + bool sizeIsInteger = false; + PyObject *pySizeMethod = PyObject_GetAttr(pyclass, PyStrings::gSize); + if (pySizeMethod && CPPOverload_Check(pySizeMethod)) { + auto *ol = (CPPOverload *)pySizeMethod; + if (ol->HasMethods() && ol->fMethodInfo->fMethods.size() == 1) { + PyObject *pyrestype = + ol->fMethodInfo->fMethods[0]->Reflex(Cppyy::Reflex::RETURN_TYPE, Cppyy::Reflex::AS_STRING); + if (pyrestype) { + sizeIsInteger = Cppyy::IsIntegerType(CPyCppyy_PyText_AsString(pyrestype)); + Py_DECREF(pyrestype); + } + } + } + Py_XDECREF(pySizeMethod); + + if (sizeIsInteger) { + bool hasIterators = (HasAttrDirect(pyclass, PyStrings::gBegin) || HasAttrInMRO(pyclass, PyStrings::gBegin)) && + (HasAttrDirect(pyclass, PyStrings::gEnd) || HasAttrInMRO(pyclass, PyStrings::gEnd)); + bool hasSubscript = HasAttrDirect(pyclass, PyStrings::gGetItem) || HasAttrInMRO(pyclass, PyStrings::gGetItem); + if (hasIterators || hasSubscript) { + Utility::AddToClass(pyclass, "__len__", "size"); + } + } } if (HasAttrDirect(pyclass, PyStrings::gContains)) { @@ -1871,7 +1908,7 @@ bool CPyCppyy::Pythonize(PyObject* pyclass, const std::string& name) std::ostringstream initdef; initdef << "namespace __cppyy_internal {\n" - << "void init_" << rname << "(" << name << "*& self"; + << "void init_" << rname << "(" << name << "** self"; bool codegen_ok = true; std::vector arg_types, arg_names, arg_defaults; arg_types.reserve(ndata); arg_names.reserve(ndata); arg_defaults.reserve(ndata); @@ -1909,7 +1946,7 @@ bool CPyCppyy::Pythonize(PyObject* pyclass, const std::string& name) initdef << ", " << arg_types[i] << " " << arg_names[i]; if (defaults_ok) initdef << " = " << arg_defaults[i]; } - initdef << ") {\n self = new " << name << "{"; + initdef << ") {\n *self = new " << name << "{"; for (std::vector::size_type i = 0; i < arg_names.size(); ++i) { if (i != 0) initdef << ", "; initdef << arg_names[i]; diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/TPyArg.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/TPyArg.cxx deleted file mode 100644 index 9906ae87493ff..0000000000000 --- a/bindings/pyroot/cppyy/CPyCppyy/src/TPyArg.cxx +++ /dev/null @@ -1,131 +0,0 @@ -// Bindings -#include "CPyCppyy.h" -#define CPYCPPYY_INTERNAL 1 -#include "CPyCppyy/TPyArg.h" -#undef CPYCPPYY_INTERNAL - - -//______________________________________________________________________________ -// Generic wrapper for arguments -// ============================= -// -// Transport class for bringing C++ values and objects from Cling to Python. It -// provides, from the selected constructor, the proper conversion to a PyObject. -// In principle, there should be no need to use this class directly: it relies -// on implicit conversions. - - -//- constructor dispatcher --------------------------------------------------- -void TPyArg::CallConstructor( - PyObject*& pyself, PyObject* pyclass, const std::vector& args) -{ - int nArgs = (int)args.size(); - PyObject* pyargs = PyTuple_New(nArgs); - for (int i = 0; i < nArgs; ++i) - PyTuple_SET_ITEM(pyargs, i, (PyObject*)args[i]); - pyself = PyObject_Call(pyclass, pyargs, nullptr); - Py_DECREF(pyargs); -} - -//---------------------------------------------------------------------------- -void CallConstructor(PyObject*& pyself, PyObject* pyclass) -{ - PyObject* pyargs = PyTuple_New(0); - pyself = PyObject_Call(pyclass, pyargs, nullptr); - Py_DECREF(pyargs); -} - -//- generic dispatcher ------------------------------------------------------- -PyObject* TPyArg::CallMethod(PyObject* pymeth, const std::vector& args) -{ - int nArgs = (int)args.size(); - PyObject* pyargs = PyTuple_New(nArgs); - for (int i = 0; i < nArgs; ++i) - PyTuple_SET_ITEM(pyargs, i, (PyObject*)args[i]); - PyObject* result = PyObject_Call(pymeth, pyargs, nullptr); - Py_DECREF(pyargs); - return result; -} - -//- destructor dispatcher ---------------------------------------------------- -void TPyArg::CallDestructor(PyObject*& pyself, PyObject*, const std::vector&) -{ - Py_XDECREF(pyself); // calls actual dtor if ref-count down to 0 -} - -//---------------------------------------------------------------------------- -void TPyArg::CallDestructor(PyObject*& pyself) -{ - Py_XDECREF(pyself); -} - -//- constructors/destructor -------------------------------------------------- -TPyArg::TPyArg(PyObject* pyobject) -{ -// Construct a TPyArg from a python object. - Py_XINCREF(pyobject); - fPyObject = pyobject; -} - -//---------------------------------------------------------------------------- -TPyArg::TPyArg(int value) -{ -// Construct a TPyArg from an integer value. - fPyObject = PyInt_FromLong(value); -} - -//---------------------------------------------------------------------------- -TPyArg::TPyArg(long value) -{ -// Construct a TPyArg from an integer value. - fPyObject = PyLong_FromLong(value); -} - -//---------------------------------------------------------------------------- -TPyArg::TPyArg(double value) -{ -// Construct a TPyArg from a double value. - fPyObject = PyFloat_FromDouble(value); -} - -//---------------------------------------------------------------------------- -TPyArg::TPyArg(const char* value) -{ -// Construct a TPyArg from a C-string. - fPyObject = CPyCppyy_PyText_FromString(value); -} - -//---------------------------------------------------------------------------- -TPyArg::TPyArg(const TPyArg& s) -{ -// Copy constructor. - Py_XINCREF(s.fPyObject); - fPyObject = s.fPyObject; -} - -//---------------------------------------------------------------------------- -TPyArg& TPyArg::operator=(const TPyArg& s) -{ -// Assignment operator. - if (this != &s) { - Py_XINCREF(s.fPyObject); - fPyObject = s.fPyObject; - } - return *this; -} - -//---------------------------------------------------------------------------- -TPyArg::~TPyArg() -{ -// Done with held PyObject. - Py_XDECREF(fPyObject); - fPyObject = nullptr; -} - -//- public members ----------------------------------------------------------- -TPyArg::operator PyObject*() const -{ -// Extract the python object. - Py_XINCREF(fPyObject); - return fPyObject; -} diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/TPyClassGenerator.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/TPyClassGenerator.cxx deleted file mode 100644 index 5d7990ac08dff..0000000000000 --- a/bindings/pyroot/cppyy/CPyCppyy/src/TPyClassGenerator.cxx +++ /dev/null @@ -1,301 +0,0 @@ -// Bindings -#include "CPyCppyy.h" -#include "PyStrings.h" -#include "TPyClassGenerator.h" -#include "Utility.h" - -#include "CPyCppyy/PyResult.h" - -// TODO: not sure if any of this still makes sense ... -#if 0 - -// ROOT -#include "TClass.h" -#include "TInterpreter.h" -#include "TROOT.h" - -// Standard -#include -#include -#include - - -//= helper ================================================================== -namespace { - - class PyGILRAII { - PyGILState_STATE m_GILState; - public: - PyGILRAII() : m_GILState(PyGILState_Ensure()) {} - ~PyGILRAII() { PyGILState_Release(m_GILState); } - }; - -} // unnamed namespace - - -//- public members ----------------------------------------------------------- -TClass* TPyClassGenerator::GetClass( const char* name, bool load ) -{ -// Just forward. - return GetClass( name, load, false ); -} - -//- public members ----------------------------------------------------------- -TClass* TPyClassGenerator::GetClass( const char* name, bool load, bool silent ) -{ -// Class generator to make python classes available to Cling - -// called if all other class generators failed, attempt to build from python class - if ( PyROOT::gDictLookupActive == true ) - return 0; // call originated from python - - if ( ! load || ! name ) - return 0; - - PyGILRAII thePyGILRAII; - -// first, check whether the name is of a module - PyObject* modules = PySys_GetObject( const_cast("modules") ); - PyObject* pyname = PyROOT_PyUnicode_FromString( name ); - PyObject* keys = PyDict_Keys( modules ); - bool isModule = PySequence_Contains( keys, pyname ); - Py_DECREF( keys ); - Py_DECREF( pyname ); - - if ( isModule ) { - // the normal TClass::GetClass mechanism doesn't allow direct returns, so - // do our own check - TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject( name ); - if ( cl ) return cl; - - std::ostringstream nsCode; - nsCode << "namespace " << name << " {\n"; - - // add all free functions - PyObject* mod = PyDict_GetItemString( modules, const_cast(name) ); - PyObject* dct = PyModule_GetDict( mod ); - keys = PyDict_Keys( dct ); - - for ( int i = 0; i < PyList_GET_SIZE( keys ); ++i ) { - PyObject* key = PyList_GET_ITEM( keys, i ); - Py_INCREF( key ); - - PyObject* attr = PyDict_GetItem( dct, key ); - Py_INCREF( attr ); - - // TODO: refactor the code below with the class method code - if ( PyCallable_Check( attr ) && \ - ! (PyClass_Check( attr ) || PyObject_HasAttr( attr, PyROOT::PyStrings::gBases )) ) { - std::string func_name = PyROOT_PyUnicode_AsString( key ); - - // figure out number of variables required - PyObject* func_code = PyObject_GetAttrString( attr, (char*)"func_code" ); - PyObject* var_names = - func_code ? PyObject_GetAttrString( func_code, (char*)"co_varnames" ) : NULL; - int nVars = var_names ? PyTuple_GET_SIZE( var_names ) : 0 /* TODO: probably large number, all default? */; - if ( nVars < 0 ) nVars = 0; - Py_XDECREF( var_names ); - Py_XDECREF( func_code ); - - nsCode << " TPyReturn " << func_name << "("; - for ( int ivar = 0; ivar < nVars; ++ivar ) { - nsCode << "const TPyArg& a" << ivar; - if ( ivar != nVars-1 ) nsCode << ", "; - } - nsCode << ") {\n"; - nsCode << " std::vector v; v.reserve(" << nVars << ");\n"; - - // add the variables - for ( int ivar = 0; ivar < nVars; ++ ivar ) - nsCode << " v.push_back(a" << ivar << ");\n"; - - // call dispatch (method or class pointer hard-wired) - nsCode << " return TPyReturn(TPyArg::CallMethod((PyObject*)" << (void*)attr << ", v)); }\n"; - } - - Py_DECREF( attr ); - Py_DECREF( key ); - } - - Py_DECREF( keys ); - - nsCode << " }"; - - if ( gInterpreter->LoadText( nsCode.str().c_str() ) ) { - TClass* klass = new TClass( name, silent ); - TClass::AddClass( klass ); - return klass; - } - - return nullptr; - } - -// determine module and class name part - std::string clName = name; - std::string::size_type pos = clName.rfind( '.' ); - - if ( pos == std::string::npos ) - return 0; // this isn't a python style class - - std::string mdName = clName.substr( 0, pos ); - clName = clName.substr( pos+1, std::string::npos ); - -// create class in namespace, if it exists (no load, silent) - bool useNS = gROOT->GetListOfClasses()->FindObject( mdName.c_str() ) != 0; - if ( ! useNS ) { - // the class itself may exist if we're using the global scope - TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject( clName.c_str() ); - if ( cl ) return cl; - } - -// locate and get class - PyObject* mod = PyImport_AddModule( const_cast< char* >( mdName.c_str() ) ); - if ( ! mod ) { - PyErr_Clear(); - return 0; // module apparently disappeared - } - - Py_INCREF( mod ); - PyObject* pyclass = - PyDict_GetItemString( PyModule_GetDict( mod ), const_cast< char* >( clName.c_str() ) ); - Py_XINCREF( pyclass ); - Py_DECREF( mod ); - - if ( ! pyclass ) { - PyErr_Clear(); // the class is no longer available?! - return 0; - } - -// get a listing of all python-side members - PyObject* attrs = PyObject_Dir( pyclass ); - if ( ! attrs ) { - PyErr_Clear(); - Py_DECREF( pyclass ); - return 0; - } - -// pre-amble Cling proxy class - std::ostringstream proxyCode; - if ( useNS ) proxyCode << "namespace " << mdName << " { "; - proxyCode << "class " << clName << " {\nprivate:\n PyObject* fPyObject;\npublic:\n"; - -// loop over and add member functions - bool hasConstructor = false, hasDestructor = false; - for ( int i = 0; i < PyList_GET_SIZE( attrs ); ++i ) { - PyObject* label = PyList_GET_ITEM( attrs, i ); - Py_INCREF( label ); - PyObject* attr = PyObject_GetAttr( pyclass, label ); - - // collect only member functions (i.e. callable elements in __dict__) - if ( PyCallable_Check( attr ) ) { - std::string mtName = PyROOT_PyUnicode_AsString( label ); - - if ( mtName == "__del__" ) { - hasDestructor = true; - proxyCode << " ~" << clName << "() { TPyArg::CallDestructor(fPyObject); }\n"; - continue; - } - - bool isConstructor = mtName == "__init__"; - if ( !isConstructor && mtName.find("__", 0, 2) == 0 ) - continue; // skip all other python special funcs - - // figure out number of variables required -#if PY_VERSION_HEX < 0x03000000 - PyObject* im_func = PyObject_GetAttrString( attr, (char*)"im_func" ); - PyObject* func_code = - im_func ? PyObject_GetAttrString( im_func, (char*)"func_code" ) : NULL; -#else - PyObject* func_code = PyObject_GetAttrString( attr, "__code__" ); -#endif - PyObject* var_names = - func_code ? PyObject_GetAttrString( func_code, (char*)"co_varnames" ) : NULL; - if (PyErr_Occurred()) PyErr_Clear(); // happens for slots; default to 0 arguments - - int nVars = var_names ? PyTuple_GET_SIZE( var_names ) - 1 /* self */ : 0 /* TODO: probably large number, all default? */; - if ( nVars < 0 ) nVars = 0; - Py_XDECREF( var_names ); - Py_XDECREF( func_code ); -#if PY_VERSION_HEX < 0x03000000 - Py_XDECREF( im_func ); -#endif - - // method declaration as appropriate - if ( isConstructor ) { - hasConstructor = true; - proxyCode << " " << clName << "("; - } else // normal method - proxyCode << " TPyReturn " << mtName << "("; - for ( int ivar = 0; ivar < nVars; ++ivar ) { - proxyCode << "const TPyArg& a" << ivar; - if ( ivar != nVars-1 ) proxyCode << ", "; - } - proxyCode << ") {\n"; - proxyCode << " std::vector v; v.reserve(" << nVars+(isConstructor ? 0 : 1) << ");\n"; - - // add the 'self' argument as appropriate - if ( ! isConstructor ) - proxyCode << " v.push_back(fPyObject);\n"; - - // then add the remaining variables - for ( int ivar = 0; ivar < nVars; ++ ivar ) - proxyCode << " v.push_back(a" << ivar << ");\n"; - - // call dispatch (method or class pointer hard-wired) - if ( ! isConstructor ) - proxyCode << " return TPyReturn(TPyArg::CallMethod((PyObject*)" << (void*)attr << ", v))"; - else - proxyCode << " TPyArg::CallConstructor(fPyObject, (PyObject*)" << (void*)pyclass << ", v)"; - proxyCode << ";\n }\n"; - } - - // no decref of attr for now (b/c of hard-wired ptr); need cleanup somehow - Py_DECREF( label ); - } - -// special case if no constructor or destructor - if ( ! hasConstructor ) - proxyCode << " " << clName << "() {\n TPyArg::CallConstructor(fPyObject, (PyObject*)" << (void*)pyclass << "); }\n"; - - if ( ! hasDestructor ) - proxyCode << " ~" << clName << "() { TPyArg::CallDestructor(fPyObject); }\n"; - -// for now, don't allow copying (ref-counting wouldn't work as expected anyway) - proxyCode << " " << clName << "(const " << clName << "&) = delete;\n"; - proxyCode << " " << clName << "& operator=(const " << clName << "&) = delete;\n"; - -// closing and building of Cling proxy class - proxyCode << "};"; - if ( useNS ) proxyCode << " }"; - - Py_DECREF( attrs ); -// done with pyclass, decref here, assuming module is kept - Py_DECREF( pyclass ); - -// body compilation - if ( ! gInterpreter->LoadText( proxyCode.str().c_str() ) ) - return nullptr; - -// done, let ROOT manage the new class - TClass* klass = new TClass( useNS ? (mdName+"::"+clName).c_str() : clName.c_str(), silent ); - TClass::AddClass( klass ); - - return klass; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Just forward; based on type name only. - -TClass* TPyClassGenerator::GetClass( const std::type_info& typeinfo, bool load, bool silent ) -{ - return GetClass( typeinfo.name(), load, silent ); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Just forward; based on type name only - -TClass* TPyClassGenerator::GetClass( const std::type_info& typeinfo, bool load ) -{ - return GetClass( typeinfo.name(), load ); -} -#endif diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/TPyClassGenerator.h b/bindings/pyroot/cppyy/CPyCppyy/src/TPyClassGenerator.h deleted file mode 100644 index ed55fa27fd6fa..0000000000000 --- a/bindings/pyroot/cppyy/CPyCppyy/src/TPyClassGenerator.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef CPYCPPYY_TPYCLASSGENERATOR -#define CPYCPPYY_TPYCLASSGENERATOR - -// TODO: not sure if any of this still makes sense ... -#if 0 - -// ROOT -#include "TClassGenerator.h" - - -class TPyClassGenerator : public TClassGenerator { -public: - virtual TClass* GetClass(const char* name, bool load); - virtual TClass* GetClass(const std::type_info& typeinfo, bool load); - virtual TClass* GetClass(const char* name, bool load, bool silent); - virtual TClass* GetClass(const std::type_info& typeinfo, bool load, bool silent); -}; - -#endif - -#endif // !CPYCPPYY_TPYCLASSGENERATOR diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/TemplateProxy.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/TemplateProxy.cxx index 9a9664c0d9a23..2f118a25d9aeb 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/TemplateProxy.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/TemplateProxy.cxx @@ -102,7 +102,7 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname, std::string ptrdef; if (PyObject_GetBuffer(itemi, &bufinfo, PyBUF_FORMAT) == 0) { for (int j = 0; j < bufinfo.ndim; ++j) ptrdef += "*"; - CPyCppyy_PyBuffer_Release(itemi, &bufinfo); + PyBuffer_Release(&bufinfo); } else { ptrdef += "*"; PyErr_Clear(); @@ -227,14 +227,7 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname, PyObject* pyol = PyObject_GetItem(dct, pycachename); if (!pyol) PyErr_Clear(); bool bIsCppOL = CPPOverload_Check(pyol); - - if (pyol && !bIsCppOL && !TemplateProxy_Check(pyol)) { - // unknown object ... leave well alone - Py_DECREF(pyol); - Py_DECREF(pycachename); - Py_DECREF(dct); - return nullptr; - } + bool bIsCppTP = TemplateProxy_Check(pyol); // find the full name if the requested one was partial PyObject* exact = nullptr; @@ -284,11 +277,18 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname, // Case 5: must be a template proxy, meaning that current template name is not // a template overload - else { + else if (bIsCppTP) { ((TemplateProxy*)pyol)->AdoptTemplate(meth->Clone()); Py_DECREF(pyol); pyol = (PyObject*)CPPOverload_New(fname, meth); // takes ownership } + // Case 6: pre-existing object is not a CPPOverload nor TemplateProxy + // we do not cache it + // as this might be a pythonization (monkey-patched func/method) + else { + Py_DECREF(pyol); + pyol = (PyObject*)CPPOverload_New(fname, meth); + } // Special Case if name was aliased (e.g. typedef in template instantiation) if (!exact && !bExactMatch) { diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx index 11f02dca8e234..c878e050c01bc 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx @@ -24,7 +24,6 @@ //- data _____________________________________________________________________ #if PY_VERSION_HEX < 0x030b0000 -dict_lookup_func CPyCppyy::gDictLookupOrg = 0; bool CPyCppyy::gDictLookupActive = false; #endif @@ -889,6 +888,33 @@ bool CPyCppyy::Utility::InitProxy(PyObject* module, PyTypeObject* pytype, const return true; } +//---------------------------------------------------------------------------- +std::map const &CPyCppyy::Utility::TypecodeMap() +{ + // See https://docs.python.org/3/library/array.html#array.array + static std::map typecodeMap{ + {"char", 'b'}, + {"unsigned char", 'B'}, +#if PY_VERSION_HEX < 0x03100000 + {"wchar_t", 'u'}, +#endif +#if PY_VERSION_HEX >= 0x030d0000 + {"Py_UCS4", 'w'}, +#endif + {"short", 'h'}, + {"unsigned short", 'H'}, + {"int", 'i'}, + {"unsigned int", 'I'}, + {"long", 'l'}, + {"unsigned long", 'L'}, + {"long long", 'q'}, + {"unsigned long long", 'Q'}, + {"float", 'f'}, + {"double", 'd'} + }; + return typecodeMap; +} + //---------------------------------------------------------------------------- Py_ssize_t CPyCppyy::Utility::GetBuffer(PyObject* pyobject, char tc, int size, void*& buf, bool check) { @@ -928,7 +954,7 @@ Py_ssize_t CPyCppyy::Utility::GetBuffer(PyObject* pyobject, char tc, int size, v if (check && bufinfo.itemsize != size) { PyErr_Format(PyExc_TypeError, "buffer itemsize (%ld) does not match expected size (%d)", bufinfo.itemsize, size); - CPyCppyy_PyBuffer_Release(pyobject, &bufinfo); + PyBuffer_Release(&bufinfo); return 0; } @@ -937,17 +963,17 @@ Py_ssize_t CPyCppyy::Utility::GetBuffer(PyObject* pyobject, char tc, int size, v buflen = bufinfo.len/bufinfo.itemsize; else if (buf && bufinfo.ndim == 1) buflen = bufinfo.shape ? bufinfo.shape[0] : bufinfo.len/bufinfo.itemsize; - CPyCppyy_PyBuffer_Release(pyobject, &bufinfo); + PyBuffer_Release(&bufinfo); if (buflen) return buflen; } else { // have buf, but format mismatch: bail out now, otherwise the old // code will return based on itemsize match - CPyCppyy_PyBuffer_Release(pyobject, &bufinfo); + PyBuffer_Release(&bufinfo); return 0; } } else if (bufinfo.obj) - CPyCppyy_PyBuffer_Release(pyobject, &bufinfo); + PyBuffer_Release(&bufinfo); PyErr_Clear(); } @@ -972,7 +998,7 @@ Py_ssize_t CPyCppyy::Utility::GetBuffer(PyObject* pyobject, char tc, int size, v (*(bufprocs->bf_getbuffer))(pyobject, &bufinfo, PyBUF_WRITABLE); buf = (char*)bufinfo.buf; Py_ssize_t buflen = bufinfo.len; - CPyCppyy_PyBuffer_Release(pyobject, &bufinfo); + PyBuffer_Release(&bufinfo); #endif if (buf && check == true) { diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h index 68bee557aaa24..dfa2e5478f6a0 100644 --- a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h +++ b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h @@ -13,7 +13,6 @@ namespace CPyCppyy { class PyCallable; #if PY_VERSION_HEX < 0x030b0000 -extern dict_lookup_func gDictLookupOrg; extern bool gDictLookupActive; #endif @@ -46,7 +45,11 @@ inline PyObject* CT2CppName(PyObject* pytc, const char* cpd, bool allow_voidp) const std::string& name = CT2CppNameS(pytc, allow_voidp); if (!name.empty()) { if (name == "const char*") cpd = ""; - return CPyCppyy_PyText_FromString((std::string{name}+cpd).c_str()); +#if PY_VERSION_HEX < 0x03000000 + return PyString_FromString((std::string{name}+cpd).c_str()); +#else + return PyUnicode_FromString((std::string{name}+cpd).c_str()); +#endif } return nullptr; } @@ -62,6 +65,8 @@ PyObject* FuncPtr2StdFunction(const std::string& retType, const std::string& sig // initialize proxy type objects bool InitProxy(PyObject* module, PyTypeObject* pytype, const char* name); +std::map const &TypecodeMap(); + // retrieve the memory buffer from pyobject, return buflength, tc (optional) is python // array.array type code, size is type size, buf will point to buffer, and if check is // true, some heuristics will be applied to check buffer compatibility with the type diff --git a/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/clingwrapper.cxx b/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/clingwrapper.cxx index d0abf7ca35362..9fbff975c626c 100644 --- a/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/clingwrapper.cxx +++ b/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/clingwrapper.cxx @@ -1247,6 +1247,18 @@ bool Cppyy::IsAggregate(TCppType_t type) return false; } +bool Cppyy::IsIntegerType(const std::string &type_name) +{ + // Test if the named type is an integer type + TypeInfo_t *ti = gInterpreter->TypeInfo_Factory(type_name.c_str()); + if (!ti) + return false; + void *qtp = gInterpreter->TypeInfo_QualTypePtr(ti); + bool result = qtp ? gInterpreter->IsIntegerType(qtp) : false; + gInterpreter->TypeInfo_Delete(ti); + return result; +} + bool Cppyy::IsDefaultConstructable(TCppType_t type) { // Test if this type has a default constructor or is a "plain old data" type @@ -1703,7 +1715,7 @@ ptrdiff_t Cppyy::GetBaseOffset(TCppType_t derived, TCppType_t base, std::ostringstream msg; msg << "failed offset calculation between " << cb->GetName() << " and " << cd->GetName(); // TODO: propagate this warning to caller w/o use of Python C-API - // PyErr_Warn(PyExc_RuntimeWarning, const_cast(msg.str().c_str())); + // PyErr_WarnEx(PyExc_RuntimeWarning, const_cast(msg.str().c_str()), 1); std::cerr << "Warning: " << msg.str() << '\n'; } diff --git a/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/cpp_cppyy.h b/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/cpp_cppyy.h index 44056f8b71d95..fbbbf21012931 100644 --- a/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/cpp_cppyy.h +++ b/bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/cpp_cppyy.h @@ -136,6 +136,8 @@ namespace Cppyy { RPY_EXPORTED bool IsAggregate(TCppType_t type); RPY_EXPORTED + bool IsIntegerType(const std::string &type_name); + RPY_EXPORTED bool IsDefaultConstructable(TCppType_t type); RPY_EXPORTED diff --git a/bindings/pyroot/cppyy/cppyy/test/pythonizables.h b/bindings/pyroot/cppyy/cppyy/test/pythonizables.h index 3d843de5fe96d..abdb4c4a7de24 100644 --- a/bindings/pyroot/cppyy/cppyy/test/pythonizables.h +++ b/bindings/pyroot/cppyy/cppyy/test/pythonizables.h @@ -123,4 +123,43 @@ class IndexableBase { class IndexableDerived : public IndexableBase {}; +//=========================================================================== +// for testing size() -> __len__ pythonization guards +class SizeReturnsInt { +public: + int size() { return 3; } + int *begin() { return m_data; } + int *end() { return m_data + 3; } + +private: + int m_data[3] = {1, 2, 3}; +}; + +class SizeReturnsNonInt { +public: + struct OptSize {}; + OptSize size() { return {}; } + int *begin() { return nullptr; } + int *end() { return nullptr; } +}; + +class SizeWithoutIterator { +public: + int size() { return 5; } + // no begin()/end() or operator[] +}; + +// for testing __len__ with fully inherited container interface +class ContainerBase { +public: + int size() { return 2; } + int *begin() { return m_data; } + int *end() { return m_data + 2; } + +private: + int m_data[2] = {10, 20}; +}; + +class InheritedContainer : public ContainerBase {}; + } // namespace pyzables diff --git a/bindings/pyroot/cppyy/cppyy/test/stltypes.h b/bindings/pyroot/cppyy/cppyy/test/stltypes.h index 31fbaf7a2a77e..6506b62f379e6 100644 --- a/bindings/pyroot/cppyy/cppyy/test/stltypes.h +++ b/bindings/pyroot/cppyy/cppyy/test/stltypes.h @@ -82,15 +82,6 @@ class stl_like_class2 { value_type& operator[](ptrdiff_t i) { return fData[i]; } }; -template -class stl_like_class3 : public stl_like_class2 { - using stl_like_class2::fData; -public: - size_t size() { return sz; } - value_type& begin() { return fData; } - value_type& end() { return fData + sz; } -}; - class stl_like_class4 { public: struct iterator { diff --git a/bindings/pyroot/cppyy/cppyy/test/templates.h b/bindings/pyroot/cppyy/cppyy/test/templates.h index 3dc96686617ee..b3c38d2514e42 100644 --- a/bindings/pyroot/cppyy/cppyy/test/templates.h +++ b/bindings/pyroot/cppyy/cppyy/test/templates.h @@ -528,7 +528,7 @@ struct Test {}; using testptr = Test *; template -bool testfun(T const &x) +bool testfun(T x) { return !(bool)x; } diff --git a/bindings/pyroot/cppyy/cppyy/test/test_advancedcpp.py b/bindings/pyroot/cppyy/cppyy/test/test_advancedcpp.py index 0b6ba190a79c0..03307937c8ab1 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_advancedcpp.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_advancedcpp.py @@ -445,10 +445,10 @@ def test09_opaque_pointer_passing(self): #assert o == cppyy.bind_object(cobj, o.__class__) #assert o == cppyy.bind_object(cobj, "some_concrete_class") assert cppyy.addressof(o) == cppyy.addressof(cppyy.bind_object(addr, some_concrete_class)) - assert o == cppyy.bind_object(addr, some_concrete_class) - assert o == cppyy.bind_object(addr, type(o)) - assert o == cppyy.bind_object(addr, o.__class__) - assert o == cppyy.bind_object(addr, "some_concrete_class") + assert o is cppyy.bind_object(addr, some_concrete_class) + assert o is cppyy.bind_object(addr, type(o)) + assert o is cppyy.bind_object(addr, o.__class__) + assert o is cppyy.bind_object(addr, "some_concrete_class") raises(TypeError, cppyy.bind_object, addr, "does_not_exist") raises(TypeError, cppyy.bind_object, addr, 1) @@ -531,13 +531,13 @@ def test12_actual_type(self): b = base_class() d = derived_class() - assert b == b.cycle(b) + assert b is b.cycle(b) assert id(b) == id(b.cycle(b)) - assert b == d.cycle(b) + assert b is d.cycle(b) assert id(b) == id(d.cycle(b)) - assert d == b.cycle(d) + assert d is b.cycle(d) assert id(d) == id(b.cycle(d)) - assert d == d.cycle(d) + assert d is d.cycle(d) assert id(d) == id(d.cycle(d)) assert isinstance(b.cycle(b), base_class) diff --git a/bindings/pyroot/cppyy/cppyy/test/test_crossinheritance.py b/bindings/pyroot/cppyy/cppyy/test/test_crossinheritance.py index caf4996d16c1e..e3699888d0e9c 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_crossinheritance.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_crossinheritance.py @@ -448,6 +448,12 @@ class MyClass4 { # as the C++ side now carries the type of the dispatcher, not the type of # the direct base class with warnings.catch_warnings(record=True) as w: + # ensure warnings are not turned into errors, even if we run python -W error + # The reason why we don't turn warnings into errors instead and just + # catch the exception is that the error would be changed into a + # more uninformative "TypeError: no python-side overrides supported ()" + warnings.simplefilter("default") + class MyPyDerived1(VD.MyClass1): pass # TODO: verify warning is given assert len(w) == 1 @@ -1139,7 +1145,7 @@ def __init__(self): def test26_no_default_ctor(self): """Make sure no default ctor is created if not viable""" - import cppyy, warnings + import cppyy cppyy.cppdef("""namespace no_default_ctor { struct NoDefCtor1 { @@ -1158,7 +1164,11 @@ class NoDefCtor3 { virtual ~NoDefCtor3() {} }; - class Simple {}; }""") + class Simple { + public: + virtual ~Simple() {} + }; + }""") ns = cppyy.gbl.no_default_ctor @@ -1170,18 +1180,16 @@ def __init__(self): with raises(TypeError): PyDerived() - with warnings.catch_warnings(record=True) as w: - class PyDerived(cppyy.multi(kls, ns.Simple)): - def __init__(self): - super(PyDerived, self).__init__() + class PyDerived(cppyy.multi(kls, ns.Simple)): + def __init__(self): + super(PyDerived, self).__init__() with raises(TypeError): PyDerived() - with warnings.catch_warnings(record=True) as w: - class PyDerived(cppyy.multi(ns.Simple, kls)): - def __init__(self): - super(PyDerived, self).__init__() + class PyDerived(cppyy.multi(ns.Simple, kls)): + def __init__(self): + super(PyDerived, self).__init__() with raises(TypeError): PyDerived() diff --git a/bindings/pyroot/cppyy/cppyy/test/test_datatypes.py b/bindings/pyroot/cppyy/cppyy/test/test_datatypes.py index 1404a5d99148d..e66e36529ece9 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_datatypes.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_datatypes.py @@ -644,7 +644,7 @@ def test09_global_ptr(self): d = gbl.get_global_pod() assert gbl.is_global_pod(d) - assert c == d + assert c is d assert id(c) == id(d) e = gbl.CppyyTestPod() @@ -2442,5 +2442,32 @@ class JetFit: public virtual JetFitTag { for i in gbl.make(): assert i.name == "NAME" + def test53_long_double_iterator(self): + """Test covering ROOT GitHub issue + https://github.com/root-project/root/issues/21732 + """ + + import cppyy + + std = cppyy.gbl.std + + N = 5 + A1 = std.array["int", N] + A2 = std.array["long double", N] + + a1 = A1() + a2 = A2() + + for i in range(len(a1)): + a1[i] = i + for i in range(len(a2)): + a2[i] = i + + for i, v in enumerate(a1): + assert v == a1[i] + + for i, v in enumerate(a2): + assert v == a2[i] + if __name__ == "__main__": exit(pytest.main(args=['-v', '-ra', __file__])) diff --git a/bindings/pyroot/cppyy/cppyy/test/test_fragile.py b/bindings/pyroot/cppyy/cppyy/test/test_fragile.py index 2181a6e18068a..b1a07477aa394 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_fragile.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_fragile.py @@ -604,16 +604,18 @@ def test25_cppdef_error_reporting(self): int add42(int i) { return i + 42; } }""") - with warnings.catch_warnings(record=True) as w: + # isolate the warning configuration + with warnings.catch_warnings(): + warnings.simplefilter("error") # turn warnings into errors + # missing return statement - cppyy.cppdef("""\ - namespace fragile { - double add42d(double d) { d + 42.; return d; } - }""") + with pytest.raises(SyntaxWarning) as exc: + cppyy.cppdef("""\ + namespace fragile { + double add42d(double d) { d + 42.; return d; } + }""") - assert len(w) == 1 - assert issubclass(w[-1].category, SyntaxWarning) - assert "return" in str(w[-1].message) + assert "return" in str(exc.value) # mix of error and warning with raises(SyntaxError): diff --git a/bindings/pyroot/cppyy/cppyy/test/test_lowlevel.py b/bindings/pyroot/cppyy/cppyy/test/test_lowlevel.py index 71c1ed63e939a..fa07805b29598 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_lowlevel.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_lowlevel.py @@ -513,6 +513,24 @@ def test15_templated_arrays_gmpxx(self): g = cppyy.gbl assert g.test15_templated_arrays_gmpxx.vector.value_type[g.std.vector[g.mpz_class]] + def test16_empy_llview_as_argument(self): + """Verify that empty LowLevelViews from nullptr can be used for C++ + function calls. This covers the problem that was reported in + https://github.com/root-project/root/issues/20687. + """ + import cppyy + + cppyy.cppdef(""" + int *getCStyleArray() { return nullptr; } + void takeCStyleArray(int *arr) {} + """) + + ll_view = cppyy.gbl.getCStyleArray() + + assert(len(ll_view) == 0) + + cppyy.gbl.takeCStyleArray(ll_view) + class TestMULTIDIMARRAYS: def setup_class(cls): diff --git a/bindings/pyroot/cppyy/cppyy/test/test_overloads.py b/bindings/pyroot/cppyy/cppyy/test/test_overloads.py index c33049d08da42..4993e8f7be2c8 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_overloads.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_overloads.py @@ -448,5 +448,24 @@ class Test14Functor { assert cppyy.gbl.test14_baz(functor) == 2 # should resolve to baz(std::function) + def test15_disallow_mutable_pointer_references(self): + """Verify that mutable pointer references (T*&) are not allowed as arguments. + """ + + import cppyy + + cppyy.cppdef(""" + struct MyClass { + int val = 0; + }; + + void changePtr(MyClass *& ptr) {} + """) + + ptr = cppyy.gbl.MyClass() + + raises(TypeError, cppyy.gbl.changePtr, ptr) + + if __name__ == "__main__": exit(pytest.main(args=['-sv', '-ra', __file__])) diff --git a/bindings/pyroot/cppyy/cppyy/test/test_pythonization.py b/bindings/pyroot/cppyy/cppyy/test/test_pythonization.py index 594c34c370f75..654f7bdc3f7f3 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_pythonization.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_pythonization.py @@ -370,6 +370,33 @@ def test10_shared_ptr_reset(self): optr.__smartptr__().reset(o2) assert optr == o2 + def test11_size_len_pythonization_guards(self): + """Verify __len__ is only installed when size() returns int and class is iterable""" + + import cppyy + + # size() returns int AND has begin/end -> __len__ installed + obj_int = cppyy.gbl.pyzables.SizeReturnsInt() + assert hasattr(obj_int, "__len__") + assert len(obj_int) == 3 + assert bool(obj_int) + + # size() returns non-integer type -> __len__ NOT installed + obj_opt = cppyy.gbl.pyzables.SizeReturnsNonInt() + assert not hasattr(obj_opt, "__len__") + assert bool(obj_opt) # should be True (valid object) + + # size() returns int but no begin/end or operator[] -> __len__ NOT installed + obj_noiter = cppyy.gbl.pyzables.SizeWithoutIterator() + assert not hasattr(obj_noiter, "__len__") + assert bool(obj_noiter) + + # fully inherited container interface -> __len__ installed via MRO + obj_inherited = cppyy.gbl.pyzables.InheritedContainer() + assert hasattr(obj_inherited, "__len__") + assert len(obj_inherited) == 2 + + ## actual test run if __name__ == "__main__": exit(pytest.main(args=['-sv', '-ra', __file__])) diff --git a/bindings/pyroot/cppyy/cppyy/test/test_regression.py b/bindings/pyroot/cppyy/cppyy/test/test_regression.py index 81c6a74fd0eda..a3cc699609df8 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_regression.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_regression.py @@ -253,7 +253,7 @@ def test11_cobject_addressing(self): a = cppyy.gbl.CObjA() co = cppyy.ll.as_cobject(a) - assert a == cppyy.bind_object(co, 'CObjA') + assert a is cppyy.bind_object(co, 'CObjA') assert a.m_int == 42 assert cppyy.bind_object(co, 'CObjA').m_int == 42 @@ -1114,9 +1114,13 @@ def test38_char16_arrays(self): len(ai.name) == 6 assert ai.name[:len(s)] == s - with warnings.catch_warnings(record=True) as w: - ai.name = u'hellowd' - assert 'too long' in str(w[-1].message) + # isolate the warning configuration + with warnings.catch_warnings(): + warnings.simplefilter("error") # turn warnings into errors + + with pytest.raises(RuntimeWarning) as exc: + ai.name = u'hellowd' + assert 'too long' in str(exc.value) # vector of objects va = cppyy.gbl.std.vector[ns.AxisInformation](N) diff --git a/bindings/pyroot/cppyy/cppyy/test/test_stltypes.py b/bindings/pyroot/cppyy/cppyy/test/test_stltypes.py index 77761e2c7d6b2..14661dd01fdf0 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_stltypes.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_stltypes.py @@ -1484,16 +1484,12 @@ def test02_STL_like_class_iterators(self): assert i == len(a)-1 - for cls in [cppyy.gbl.stl_like_class2, cppyy.gbl.stl_like_class3]: - b = cls[float, 2]() - b[0] = 27; b[1] = 42 - limit = len(b)+1 - for x in b: - limit -= 1 - assert limit and "iterated too far!" - assert x in [27, 42] - assert x == 42 - del x, b + b = cppyy.gbl.stl_like_class2[float, 2]() + b[0] = 27 + b[1] = 42 + assert len(b) == 2 + for i in range(len(b)): + assert b[i] in [27, 42] for num in [4, 5, 6, 7]: cls = getattr(cppyy.gbl, 'stl_like_class%d' % num) @@ -1982,7 +1978,7 @@ def test04_tuple_lifeline(self): assert s1.fInt == 42 assert s2.fInt == 42 - @mark.xfail(strict=True, condition=IS_WINDOWS, reason="The wrong values are read back from the tuple!") + @mark.xfail(run=False, condition=IS_WINDOWS, reason="The wrong values are read back from the tuple!") def test05_tuple_assignment_operator(self): """Check that using std::tuple<>::operator= works. This used to fail because ROOT uses a different type to represent @@ -2216,6 +2212,75 @@ def test01_span_iterators(self): # internally. assert [b for b in s] == l1 + def test02_span_argument_conversions(self): + """ + Test conversion of various Python objects to std::span arguments. + + Covers: + 1) Python proxy spans + 2) NumPy arrays + 3) array.array + 4) Type mismatch errors + 5) std::vector implicit conversion + 6) const std::span behavior + """ + import cppyy + import numpy as np + import array + import pytest + + cppyy.cppdef(""" + #include + #include + + template + size_t sum_span(std::span s) { + size_t total = 0; + for (size_t i = 0; i < s.size(); ++i) + total += (size_t)s[i]; + return total; + } + + template + size_t sum_span_const(std::span s) { + size_t total = 0; + for (size_t i = 0; i < s.size(); ++i) + total += (size_t)s[i]; + return total; + } + """) + + data = [1., 2., 3.] + expected = sum(data) + + # 1) Python proxy span + v = cppyy.gbl.std.vector["double"](data) + s = cppyy.gbl.std.span["double"](v) + assert cppyy.gbl.sum_span["double"](s) == expected + assert cppyy.gbl.sum_span_const["double"](s) == expected + + # 2) NumPy array + np_arr = np.array(data, dtype=np.float64) + assert cppyy.gbl.sum_span["double"](np_arr) == expected + assert cppyy.gbl.sum_span_const["double"](np_arr) == expected + + # 3) array.array + arr = array.array('d', data) + assert cppyy.gbl.sum_span["double"](arr) == expected + assert cppyy.gbl.sum_span_const["double"](arr) == expected + + # 4) Type mismatch → should raise TypeError + np_double = np.array([1.0, 2.0, 3.0], dtype=np.float32) + with pytest.raises(TypeError): + cppyy.gbl.sum_span["double"](np_double) + + # 5) std::vector implicit conversion + v2 = cppyy.gbl.std.vector["double"](data) + assert cppyy.gbl.sum_span["double"](v2) == expected + assert cppyy.gbl.sum_span_const["double"](v2) == expected + + # 6) const span behaves the same (already checked above, but explicit case) + assert cppyy.gbl.sum_span_const["double"](np_arr) == expected if __name__ == "__main__": exit(pytest.main(args=['-v', '-ra', __file__])) diff --git a/bindings/pyroot/cppyy/cppyy/test/test_templates.py b/bindings/pyroot/cppyy/cppyy/test/test_templates.py index 7c2ea9bdfb53a..51ca569e1559e 100644 --- a/bindings/pyroot/cppyy/cppyy/test/test_templates.py +++ b/bindings/pyroot/cppyy/cppyy/test/test_templates.py @@ -1133,9 +1133,7 @@ def test33_using_template_argument(self): assert ns.testfun["testptr"](cppyy.bind_object(cppyy.nullptr, ns.Test)) - # TODO: raises TypeError; the problem is that the type is resolved - # from UsingPtr::Test*const& to UsingPtr::Test*& (ie. `const` is lost) - # assert ns.testfun["UsingPtr::testptr"](cppyy.nullptr) + assert ns.testfun["UsingPtr::testptr"](cppyy.nullptr) assert ns.testptr.__name__ == "Test" assert ns.testptr.__cpp_name__ == "UsingPtr::Test*" @@ -1206,6 +1204,28 @@ def test36_constructor_implicit_conversion(self): a = ns.S(1, 2) assert a.m_a == 1 + + def test37_monkey_patching_template_proxy(self): + """Monkey patching Template Proxy""" + import cppyy + from cppyy import gbl + + cppyy.cppdef(r""" + struct MyMonkey { + template + bool m(std::vector v) { return true; } + + template + bool m(int i) { return false; } + }; + """) + + gbl.MyMonkey._m = gbl.MyMonkey.m + gbl.MyMonkey.m = lambda self, x: gbl.MyMonkey._m(self, x) + a = gbl.MyMonkey() + assert not a.m(42) + assert a.m([1, 2, 3]) + assert not a.m(42) class TestTEMPLATED_TYPEDEFS: diff --git a/bindings/pyroot/pythonizations/CMakeLists.txt b/bindings/pyroot/pythonizations/CMakeLists.txt index 622f38c4ade74..2cd037d234b6c 100644 --- a/bindings/pyroot/pythonizations/CMakeLists.txt +++ b/bindings/pyroot/pythonizations/CMakeLists.txt @@ -31,6 +31,17 @@ set(libname ROOTPythonizations) add_library(${libname} SHARED ${cpp_sources}) +# Use what is in the limited API since Python 3.11, if we build with a lower +# Python version, we don't bother using the limited API. +if (Python3_VERSION VERSION_GREATER_EQUAL "3.11") + # On Windows we can't use the stable ABI yet: it requires linking against a + # different libpython, so as long as we don't build all translation units in + # the ROOT Pythonization library with the stable ABI we should not use it. + if(NOT MSVC) + target_compile_options(${libname} PRIVATE -DPy_LIMITED_API=0x030B0000) + endif() +endif() + # Set the suffix to '.so' and the prefix to 'lib' set_target_properties(${libname} PROPERTIES ${ROOT_LIBRARY_PROPERTIES_NO_VERSION}) target_link_libraries(${libname} PUBLIC Core Tree CPyCppyy) diff --git a/bindings/pyroot/pythonizations/python/ROOT/_facade.py b/bindings/pyroot/pythonizations/python/ROOT/_facade.py index 9254b1341dc3e..da8b6681ec2f2 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_facade.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_facade.py @@ -43,6 +43,86 @@ def __setattr__(self, name, value): return setattr(self._gROOT, name, value) +class TDirectoryPythonAdapter: + """Class analogous to the `ROOT::Internal::TDirectoryAtomicAdapter` on the + C++ side, implementing the semantics that is expected from a + `TDirectory *&` to the global directory (which is what gDirectory was + originally), but in a thread-safe way. + + On the C++ side the following trick is used in TDirectory.h to achieve this + We're re-implementing the expected semantics in Python, because the way how + it is implemented in C++ is too contrived for it to get Pythonized + automatically: + + ```C++ + #define gDirectory (::ROOT::Internal::TDirectoryAtomicAdapter{}) + ``` + + So in C++, gDirectory is an adapter object that lazily converts to current + TDirectory when you use it. It's implemented as as a preprocessor macro, + which is then pretending to be a `TDirectory *` to the ROOT reflection system + in TROOT.cxx: + + ```C++ + TGlobalMappedFunction::MakeFunctor("gDirectory", "TDirectory*", TDirectory::CurrentDirectory); + ``` + + This is quite hacky, and it is ambiguous to the the dynamic Python bindings + layer at which point the implicit conversion to the current directory + pointer should happen. + + For this reason, it's better to re-implement a specific adapter for Python, + which skips all of that. + + Note: the C++ adapter also implements an assignment operator (operator=), + but since this concept doesn't exist in Python outside data member + re-assignment, it is not implemented here. + """ + + def _current_directory(self): + import ROOT + + return ROOT.TDirectory.CurrentDirectory().load() + + def __getattr__(self, name): + return getattr(self._current_directory(), name) + + def __str__(self): + return str(self._current_directory()) + + def __repr__(self): + return repr(self._current_directory()) + + def __eq__(self, other): + import ROOT + + if other is self: + return True + cd = self._current_directory() + if cd == ROOT.nullptr: + return other == ROOT.nullptr + return cd.IsEqual(other) + + def __ne__(self, other): + import ROOT + + if other is self: + return False + cd = self._current_directory() + if cd == ROOT.nullptr: + return other != ROOT.nullptr + return not cd.IsEqual(other) + + def __bool__(self): + import ROOT + + return self._current_directory() != ROOT.nullptr + + def __cast_cpp__(self): + """Casting to TDirectory for use in C++ functions.""" + return self._current_directory() + + def _subimport(name): # type: (str) -> types.ModuleType """ @@ -62,7 +142,7 @@ def __init__(self, module, is_ipython): self.__all__ = module.__all__ self.__name__ = module.__name__ self.__file__ = module.__file__ - self.__cached__ = module.__cached__ + self.__spec__ = module.__spec__ self.__path__ = module.__path__ self.__doc__ = module.__doc__ self.__package__ = module.__package__ @@ -71,6 +151,10 @@ def __init__(self, module, is_ipython): # Inject gROOT global self.gROOT = _gROOTWrapper(self) + # Inject the gDirectory adapter, mimicking the behavior of the + # gDirectory preprocessor macro on the C++ side + self.gDirectory = TDirectoryPythonAdapter() + # Initialize configuration self.PyConfig = PyROOTConfiguration() @@ -208,7 +292,7 @@ def _finalSetup(self): if not self.gROOT.IsBatch() and self.PyConfig.StartGUIThread: self.app.init_graphics(self._cppyy.gbl.gEnv, self._cppyy.gbl.gSystem) - # The automatic conversion of ordinary obejcts to smart pointers is + # The automatic conversion of ordinary objects to smart pointers is # disabled for ROOT because it can cause trouble with overload # resolution. If a function has overloads for both ordinary objects and # smart pointers, then the implicit conversion to smart pointers can diff --git a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_rdataframe.py b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_rdataframe.py index 5a970b3009800..4d56d6c2c7dd8 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_rdataframe.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_rdataframe.py @@ -549,6 +549,7 @@ def _MakeNumpyDataFrame(np_dict): using the keys as column names and the numpy arrays as data. """ import ROOT + from ROOT.libROOTPythonizations import PyObjRefCounterAsStdAny if not isinstance(np_dict, dict): raise RuntimeError("Object not convertible: Python object is not a dictionary.") @@ -558,42 +559,10 @@ def _MakeNumpyDataFrame(np_dict): args = (_make_name_rvec_pair(key, value) for key, value in np_dict.items()) - # How we keep the NumPy arrays around as long as the RDataSource is alive: - # - # 1. Create a new dict with references to the NumPy arrays and take - # ownership of it on the C++ side (Py_INCREF). We use a copy of the - # original dict, because otherwise the caller of _MakeNumpyDataFrame - # can invalidate our cache by mutating the np_dict after the call. - # - # 2. The C++ side gets a deleter std::function, calling Py_DECREF when the - # RDataSource is destroyed. - - def _ensure_deleter_declared(): - # If the function is already known to ROOT, skip declaring again - try: - ROOT.__ROOT_Internal.MakePyDeleter - return - except AttributeError: - pass - - ROOT.gInterpreter.Declare( - r""" - #include - - namespace __ROOT_Internal { - - inline std::function MakePyDeleter(std::uintptr_t ptr) { - PyObject *obj = reinterpret_cast(ptr); - Py_INCREF(obj); - return [obj](){ Py_DECREF(obj); }; - } - - } // namespace __ROOT_Internal - """ - ) - - _ensure_deleter_declared() + # To keep the NumPy arrays around as long as the RDataSource is alive, + # create a new dict with references to the NumPy arrays, and pass a + # reference count to the C++ side via std::any. We use a copy of the + # original dict, because otherwise the caller of _MakeNumpyDataFrame can + # invalidate our cache by mutating the np_dict after the call. - np_dict_copy = dict(**np_dict) - key = id(np_dict_copy) - return ROOT.Internal.RDF.MakeRVecDataFrame(ROOT.__ROOT_Internal.MakePyDeleter(key), *args) + return ROOT.Internal.RDF.MakeRVecDataFrame(PyObjRefCounterAsStdAny(dict(**np_dict)), *args) diff --git a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabspdf.py b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabspdf.py index ec8a6ccf80b36..be5991080c176 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabspdf.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabspdf.py @@ -12,38 +12,7 @@ from ._rooabsreal import RooAbsReal -from ._utils import _kwargs_to_roocmdargs, cpp_signature - - -def _pack_cmd_args(*args, **kwargs): - # Pack command arguments passed into a RooLinkedList. - - import ROOT - - # If the second argument is already a RooLinkedList, do nothing - if len(kwargs) == 0 and len(args) == 1 and isinstance(args[0], ROOT.RooLinkedList): - return args[0] - - # Transform keyword arguments to RooCmdArgs - args, kwargs = _kwargs_to_roocmdargs(*args, **kwargs) - - # All keyword arguments should be transformed now - assert len(kwargs) == 0 - - # Put RooCmdArgs in a RooLinkedList - cmd_list = ROOT.RooLinkedList() - for cmd in args: - if not isinstance(cmd, ROOT.RooCmdArg): - raise TypeError("This function only takes RooFit command arguments.") - cmd_list.Add(cmd) - - # The RooLinkedList passed to functions like fitTo() is expected to be - # non-owning. To make sure that the RooCmdArgs live long enough, we attach - # them as an attribute of the output list, such that the Python reference - # counter doesn't hit zero. - cmd_list._owning_pylist = args - - return cmd_list +from ._utils import _kwargs_to_roocmdargs, cpp_signature, _pack_cmd_args class RooAbsPdf(RooAbsReal): diff --git a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabsreal.py b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabsreal.py index 7017f66e0d21a..46ebfeb4f5467 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabsreal.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_rooabsreal.py @@ -12,7 +12,7 @@ ################################################################################ -from ._utils import _kwargs_to_roocmdargs, cpp_signature +from ._utils import _kwargs_to_roocmdargs, cpp_signature, _pack_cmd_args class RooAbsReal(object): @@ -110,8 +110,7 @@ def createChi2(self, *args, **kwargs): """ import ROOT - args, kwargs = _kwargs_to_roocmdargs(*args, **kwargs) - out = self._createChi2(*args, **kwargs) + out = self._createChi2["RooLinkedList const&"](args[0], _pack_cmd_args(*args[1:], **kwargs)) ROOT.SetOwnership(out, True) return out @@ -126,8 +125,7 @@ def chi2FitTo(self, *args, **kwargs): """ import ROOT - args, kwargs = _kwargs_to_roocmdargs(*args, **kwargs) - out = self._chi2FitTo(*args, **kwargs) + out = self._chi2FitTo["RooLinkedList const&"](args[0], _pack_cmd_args(*args[1:], **kwargs)) ROOT.SetOwnership(out, True) return out diff --git a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_utils.py b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_utils.py index 96a8212a1764e..775eae4da1498 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_utils.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_utils.py @@ -53,6 +53,37 @@ def getter(k, v): return args, {} +def _pack_cmd_args(*args, **kwargs): + # Pack command arguments passed into a RooLinkedList. + + import ROOT + + # If the second argument is already a RooLinkedList, do nothing + if len(kwargs) == 0 and len(args) == 1 and isinstance(args[0], ROOT.RooLinkedList): + return args[0] + + # Transform keyword arguments to RooCmdArgs + args, kwargs = _kwargs_to_roocmdargs(*args, **kwargs) + + # All keyword arguments should be transformed now + assert len(kwargs) == 0 + + # Put RooCmdArgs in a RooLinkedList + cmd_list = ROOT.RooLinkedList() + for cmd in args: + if not isinstance(cmd, ROOT.RooCmdArg): + raise TypeError("This function only takes RooFit command arguments.") + cmd_list.Add(cmd) + + # The RooLinkedList passed to functions like fitTo() is expected to be + # non-owning. To make sure that the RooCmdArgs live long enough, we attach + # them as an attribute of the output list, such that the Python reference + # counter doesn't hit zero. + cmd_list._owning_pylist = args + + return cmd_list + + def _dict_to_flat_map(arg_dict, allowed_val_dict): """ Helper function to convert python dict to std::map. diff --git a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/layers/permute.py b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/layers/permute.py index f08f9373d12fd..358eb18ecedff 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/layers/permute.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/layers/permute.py @@ -26,11 +26,7 @@ def MakeKerasPermute(layer): if SOFIE.ConvertStringToType(fLayerDType) == SOFIE.ETensorType.FLOAT: if len(fAttributePermute) > 0: fAttributePermute = [0] + fAttributePermute # for the batch dimension from the input - op = SOFIE.ROperator_Transpose("float")( - fAttributePermute, fLayerInputName, fLayerOutputName - ) # SOFIE.fPermuteDims - else: - op = SOFIE.ROperator_Transpose("float")(fLayerInputName, fLayerOutputName) + op = SOFIE.ROperator_Transpose(fAttributePermute, fLayerInputName, fLayerOutputName) return op else: raise RuntimeError( diff --git a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/parser.py b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/parser.py index c4a378eab8481..4cf29aedd7faf 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/parser.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_tmva/_sofie/_parser/_keras/parser.py @@ -161,7 +161,7 @@ def move_operator(op): fLayerOutput = outputs[0] if fLayerType == "GlobalAveragePooling2D": if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") + op = SOFIE.ROperator_Transpose([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") rmodel.AddOperator(move_operator(op)) inputs[0] = LayerName + "PreTrans" outputs[0] = LayerName + "Squeeze" @@ -186,23 +186,23 @@ def move_operator(op): fAttrPerm = list(range(0, num_input_shapes)) fAttrPerm[1] = axis fAttrPerm[axis] = 1 - op = SOFIE.ROperator_Transpose("float")(fAttrPerm, inputs[0], LayerName + "PreTrans") + op = SOFIE.ROperator_Transpose(fAttrPerm, inputs[0], LayerName + "PreTrans") rmodel.AddOperator(move_operator(op)) inputs[0] = LayerName + "PreTrans" outputs[0] = LayerName + "PostTrans" rmodel.AddOperator(move_operator(mapKerasLayer[fLayerType](layer_data))) - op = SOFIE.ROperator_Transpose("float")(fAttrPerm, LayerName + "PostTrans", fLayerOutput) + op = SOFIE.ROperator_Transpose(fAttrPerm, LayerName + "PostTrans", fLayerOutput) rmodel.AddOperator(move_operator(op)) elif fLayerType == "MaxPooling2D" or fLayerType == "AveragePooling2D": if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") + op = SOFIE.ROperator_Transpose([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") rmodel.AddOperator(move_operator(op)) inputs[0] = LayerName + "PreTrans" outputs[0] = LayerName + "PostTrans" rmodel.AddOperator(move_operator(mapKerasLayer[fLayerType](layer_data))) if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")([0, 2, 3, 1], LayerName + "PostTrans", fLayerOutput) + op = SOFIE.ROperator_Transpose([0, 2, 3, 1], LayerName + "PostTrans", fLayerOutput) rmodel.AddOperator(move_operator(op)) else: @@ -237,7 +237,7 @@ def move_operator(op): # if the data format is channels last (can be set to channels first by the user). if fLayerType == "Conv2D": if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") + op = SOFIE.ROperator_Transpose([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") rmodel.AddOperator(move_operator(op)) inputs[0] = LayerName + "PreTrans" layer_data["layerInput"] = inputs @@ -248,7 +248,7 @@ def move_operator(op): Activation_layer_input = LayerName + fLayerType if fLayerType == "Conv2D": if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")( + op = SOFIE.ROperator_Transpose( [0, 2, 3, 1], LayerName + fLayerType, LayerName + "PostTrans" ) rmodel.AddOperator(move_operator(op)) @@ -268,7 +268,7 @@ def move_operator(op): outputs = layer_data["layerOutput"] fLayerOutput = outputs[0] if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") + op = SOFIE.ROperator_Transpose([0, 3, 1, 2], inputs[0], LayerName + "PreTrans") rmodel.AddOperator(move_operator(op)) inputs[0] = LayerName + "PreTrans" layer_data["layerInput"] = inputs @@ -276,7 +276,7 @@ def move_operator(op): rmodel.AddOperator(move_operator(mapKerasLayerWithActivation[fLayerType](layer_data))) if fLayerType == "Conv2D": if layer_data["channels_last"]: - op = SOFIE.ROperator_Transpose("float")([0, 2, 3, 1], LayerName + "PostTrans", fLayerOutput) + op = SOFIE.ROperator_Transpose([0, 2, 3, 1], LayerName + "PostTrans", fLayerOutput) rmodel.AddOperator(move_operator(op)) return rmodel else: diff --git a/bindings/pyroot/pythonizations/src/CPPInstancePyz.cxx b/bindings/pyroot/pythonizations/src/CPPInstancePyz.cxx index 021e0834776b3..8f1f24d32c082 100644 --- a/bindings/pyroot/pythonizations/src/CPPInstancePyz.cxx +++ b/bindings/pyroot/pythonizations/src/CPPInstancePyz.cxx @@ -9,18 +9,14 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ +#include + // Bindings #include "CPyCppyy/API.h" -#include "../../cppyy/CPyCppyy/src/CPyCppyy.h" -#include "../../cppyy/CPyCppyy/src/CPPInstance.h" -#include "../../cppyy/CPyCppyy/src/CustomPyTypes.h" - #include "PyROOTPythonize.h" #include "TBufferFile.h" -using namespace CPyCppyy; - namespace PyROOT { extern PyObject *gRootModule; } @@ -40,18 +36,18 @@ PyObject *PyROOT::CPPInstanceExpand(PyObject * /*self*/, PyObject *args) PyObject *pybuf = 0, *pyname = 0; if (!PyArg_ParseTuple(args, "O!O!:__expand__", &PyBytes_Type, &pybuf, &PyBytes_Type, &pyname)) return 0; - const char *clname = PyBytes_AS_STRING(pyname); + const char *clname = PyBytes_AsString(pyname); // TBuffer and its derived classes can't write themselves, but can be created // directly from the buffer, so handle them in a special case void *newObj = 0; if (strcmp(clname, "TBufferFile") == 0) { TBufferFile *buf = new TBufferFile(TBuffer::kWrite); - buf->WriteFastArray(PyBytes_AS_STRING(pybuf), PyBytes_GET_SIZE(pybuf)); + buf->WriteFastArray(PyBytes_AsString(pybuf), PyBytes_Size(pybuf)); newObj = buf; } else { // use the PyString macro's to by-pass error checking; do not adopt the buffer, // as the local TBufferFile can go out of scope (there is no copying) - TBufferFile buf(TBuffer::kRead, PyBytes_GET_SIZE(pybuf), PyBytes_AS_STRING(pybuf), kFALSE); + TBufferFile buf(TBuffer::kRead, PyBytes_Size(pybuf), PyBytes_AsString(pybuf), kFALSE); newObj = buf.ReadObjectAny(0); } PyObject *result = CPyCppyy::Instance_FromVoidPtr(newObj, clname, /*python_owns=*/true); @@ -62,7 +58,7 @@ PyObject *PyROOT::CPPInstanceExpand(PyObject * /*self*/, PyObject *args) /// Turn the object proxy instance into a character stream and return for /// pickle, together with the callable object that can restore the stream /// into the object proxy instance. -PyObject *op_reduce(PyObject *self) +PyObject *op_reduce(PyObject *self, PyObject * /*args*/) { // keep a borrowed reference around to the callable function for expanding; // because it is borrowed, it means that there can be no pickling during the @@ -71,13 +67,11 @@ PyObject *op_reduce(PyObject *self) // TBuffer and its derived classes can't write themselves, but can be created // directly from the buffer, so handle them in a special case - static Cppyy::TCppType_t s_bfClass = Cppyy::GetScope("TBufferFile"); - TBufferFile *buff = 0; - Cppyy::TCppType_t selfClass = ((CPPInstance *)self)->ObjectIsA(); - if (selfClass == s_bfClass) { + TBufferFile *buff = nullptr; + std::string className = CPyCppyy::Instance_GetScopedFinalName(self); + if (className == "TBufferFile") { buff = (TBufferFile *)CPyCppyy::Instance_AsVoidPtr(self); } else { - auto className = Cppyy::GetScopedFinalName(selfClass); if (className.find("__cppyy_internal::Dispatcher") == 0) { PyErr_Format(PyExc_IOError, "generic streaming of Python objects whose class derives from a C++ class is not supported. " @@ -92,7 +86,7 @@ PyObject *op_reduce(PyObject *self) // to delete if (s_buff.WriteObjectAny(CPyCppyy::Instance_AsVoidPtr(self), TClass::GetClass(className.c_str())) != 1) { PyErr_Format(PyExc_IOError, "could not stream object of type %s", - Cppyy::GetScopedFinalName(selfClass).c_str()); + className.c_str()); return 0; } buff = &s_buff; @@ -101,13 +95,13 @@ PyObject *op_reduce(PyObject *self) // the buffer contents; use a string for the class name, used when casting // on reading back in (see CPPInstanceExpand defined above) PyObject *res2 = PyTuple_New(2); - PyTuple_SET_ITEM(res2, 0, PyBytes_FromStringAndSize(buff->Buffer(), buff->Length())); - PyTuple_SET_ITEM(res2, 1, PyBytes_FromString(Cppyy::GetScopedFinalName(selfClass).c_str())); + PyTuple_SetItem(res2, 0, PyBytes_FromStringAndSize(buff->Buffer(), buff->Length())); + PyTuple_SetItem(res2, 1, PyBytes_FromString(className.c_str())); PyObject *result = PyTuple_New(2); Py_INCREF(s_expand); - PyTuple_SET_ITEM(result, 0, s_expand); - PyTuple_SET_ITEM(result, 1, res2); + PyTuple_SetItem(result, 0, s_expand); + PyTuple_SetItem(result, 1, res2); return result; } @@ -122,6 +116,6 @@ PyObject *op_reduce(PyObject *self) /// so that it can be injected in CPPInstance PyObject *PyROOT::AddCPPInstancePickling(PyObject * /*self*/, PyObject * /*args*/) { - CPPInstance::ReduceMethod() = op_reduce; + CPyCppyy::Instance_SetReduceMethod((PyCFunction)op_reduce); Py_RETURN_NONE; } diff --git a/bindings/pyroot/pythonizations/src/GenericPyz.cxx b/bindings/pyroot/pythonizations/src/GenericPyz.cxx index 3e5ace48241d5..97438514d9f0e 100644 --- a/bindings/pyroot/pythonizations/src/GenericPyz.cxx +++ b/bindings/pyroot/pythonizations/src/GenericPyz.cxx @@ -13,8 +13,7 @@ #include "CPyCppyy/API.h" -#include "../../cppyy/CPyCppyy/src/CPyCppyy.h" -#include "../../cppyy/CPyCppyy/src/CPPInstance.h" +#include "../../cppyy/CPyCppyy/src/Cppyy.h" #include "../../cppyy/CPyCppyy/src/Utility.h" #include "PyROOTPythonize.h" @@ -25,15 +24,6 @@ #include -namespace { - -std::string GetScopedFinalNameFromPyObject(const PyObject *pyobj) -{ - return Cppyy::GetScopedFinalName(((CPyCppyy::CPPInstance *)pyobj)->ObjectIsA()); -} - -} // namespace - using namespace CPyCppyy; // We take as unique identifier the declId of the class to @@ -75,7 +65,7 @@ PyObject *ClingPrintValue(PyObject *self, PyObject * /* args */) gInterpreter->Declare(printerCode.c_str()); } - const std::string className = GetScopedFinalNameFromPyObject(self); + const std::string className = CPyCppyy::Instance_GetScopedFinalName(self); std::string printResult; diff --git a/bindings/pyroot/pythonizations/src/PyROOTModule.cxx b/bindings/pyroot/pythonizations/src/PyROOTModule.cxx index dff7f6f09ad5f..d6ba1aa297b6d 100644 --- a/bindings/pyroot/pythonizations/src/PyROOTModule.cxx +++ b/bindings/pyroot/pythonizations/src/PyROOTModule.cxx @@ -15,8 +15,6 @@ // Cppyy #include "CPyCppyy/API.h" -#include "../../cppyy/CPyCppyy/src/CallContext.h" -#include "../../cppyy/CPyCppyy/src/ProxyWrappers.h" // ROOT #include "TInterpreter.h" @@ -42,9 +40,21 @@ PyObject *RegisterConverterAlias(PyObject * /*self*/, PyObject *args) PyObject *name = nullptr; PyObject *target = nullptr; - PyArg_ParseTuple(args, "UU:RegisterConverterAlias", &name, &target); + if (!PyArg_ParseTuple(args, "UU:RegisterConverterAlias", &name, &target)) { + return nullptr; + } - CPyCppyy::RegisterConverterAlias(PyUnicode_AsUTF8(name), PyUnicode_AsUTF8(target)); + const char *nameStr = PyUnicode_AsUTF8AndSize(name, nullptr); + if (!nameStr) { + return nullptr; + } + + const char *targetStr = PyUnicode_AsUTF8AndSize(target, nullptr); + if (!targetStr) { + return nullptr; + } + + CPyCppyy::RegisterConverterAlias(nameStr, targetStr); Py_RETURN_NONE; } @@ -54,9 +64,21 @@ PyObject *RegisterExecutorAlias(PyObject * /*self*/, PyObject *args) PyObject *name = nullptr; PyObject *target = nullptr; - PyArg_ParseTuple(args, "UU:RegisterExecutorAlias", &name, &target); + if (!PyArg_ParseTuple(args, "UU:RegisterExecutorAlias", &name, &target)) { + return nullptr; + } - CPyCppyy::RegisterExecutorAlias(PyUnicode_AsUTF8(name), PyUnicode_AsUTF8(target)); + const char *nameStr = PyUnicode_AsUTF8AndSize(name, nullptr); + if (!nameStr) { + return nullptr; + } + + const char *targetStr = PyUnicode_AsUTF8AndSize(target, nullptr); + if (!targetStr) { + return nullptr; + } + + CPyCppyy::RegisterExecutorAlias(nameStr, targetStr); Py_RETURN_NONE; } @@ -75,7 +97,7 @@ class PyObjRefCounter final { void Reset(PyObject *object) { if (fObject) { - Py_DECREF(fObject); + Py_DecRef(fObject); fObject = nullptr; } if (object) { @@ -122,50 +144,83 @@ PyObject *PyObjRefCounterAsStdAny(PyObject * /*self*/, PyObject *args) /*python_owns=*/true); } +// Helper function to get the pointer to a buffer (heavily simplified copy of +// CPyCppyy::Utility::GetBuffer). +void GetBuffer(PyObject *pyobject, void *&buf) +{ + buf = nullptr; + + // Exclude text-like objects (policy decision) + if (PyBytes_Check(pyobject) || PyUnicode_Check(pyobject)) + return; + + // Fast path: bytearray + if (PyByteArray_CheckExact(pyobject)) { + buf = PyByteArray_AsString(pyobject); + return; + } + + // Buffer protocol + if (PyObject_CheckBuffer(pyobject)) { + // Avoid potential issues with empty sequences + if (PySequence_Check(pyobject) && PySequence_Size(pyobject) == 0) + return; + + Py_buffer view; + if (PyObject_GetBuffer(pyobject, &view, PyBUF_SIMPLE) == 0) { + if (view.buf && view.len > 0) + buf = view.buf; + PyBuffer_Release(&view); + } else { + PyErr_Clear(); + } + } +} + } // namespace PyROOT // Methods offered by the interface static PyMethodDef gPyROOTMethods[] = { - {(char *)"AddCPPInstancePickling", (PyCFunction)PyROOT::AddCPPInstancePickling, METH_NOARGS, - (char *)"Add a custom pickling mechanism for Cppyy Python proxy objects"}, - {(char *)"GetBranchAttr", (PyCFunction)PyROOT::GetBranchAttr, METH_VARARGS, - (char *)"Allow to access branches as tree attributes"}, - {(char *)"AddTClassDynamicCastPyz", (PyCFunction)PyROOT::AddTClassDynamicCastPyz, METH_VARARGS, - (char *)"Cast the void* returned by TClass::DynamicCast to the right type"}, - {(char *)"BranchPyz", (PyCFunction)PyROOT::BranchPyz, METH_VARARGS, - (char *)"Fully enable the use of TTree::Branch from Python"}, - {(char *)"AddPrettyPrintingPyz", (PyCFunction)PyROOT::AddPrettyPrintingPyz, METH_VARARGS, - (char *)"Add pretty printing pythonization"}, - {(char *)"InitApplication", (PyCFunction)PyROOT::RPyROOTApplication::InitApplication, METH_VARARGS, - (char *)"Initialize interactive ROOT use from Python"}, - {(char *)"InstallGUIEventInputHook", (PyCFunction)PyROOT::RPyROOTApplication::InstallGUIEventInputHook, METH_NOARGS, - (char *)"Install an input hook to process GUI events"}, - {(char *)"_CPPInstance__expand__", (PyCFunction)PyROOT::CPPInstanceExpand, METH_VARARGS, - (char *)"Deserialize a pickled object"}, - {(char *)"JupyROOTExecutor", (PyCFunction)JupyROOTExecutor, METH_VARARGS, (char *)"Create JupyROOTExecutor"}, - {(char *)"JupyROOTDeclarer", (PyCFunction)JupyROOTDeclarer, METH_VARARGS, (char *)"Create JupyROOTDeclarer"}, - {(char *)"JupyROOTExecutorHandler_Clear", (PyCFunction)JupyROOTExecutorHandler_Clear, METH_NOARGS, - (char *)"Clear JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_Ctor", (PyCFunction)JupyROOTExecutorHandler_Ctor, METH_NOARGS, - (char *)"Create JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_Poll", (PyCFunction)JupyROOTExecutorHandler_Poll, METH_NOARGS, - (char *)"Poll JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_EndCapture", (PyCFunction)JupyROOTExecutorHandler_EndCapture, METH_NOARGS, - (char *)"End capture JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_InitCapture", (PyCFunction)JupyROOTExecutorHandler_InitCapture, METH_NOARGS, - (char *)"Init capture JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_GetStdout", (PyCFunction)JupyROOTExecutorHandler_GetStdout, METH_NOARGS, - (char *)"Get stdout JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_GetStderr", (PyCFunction)JupyROOTExecutorHandler_GetStderr, METH_NOARGS, - (char *)"Get stderr JupyROOTExecutorHandler"}, - {(char *)"JupyROOTExecutorHandler_Dtor", (PyCFunction)JupyROOTExecutorHandler_Dtor, METH_NOARGS, - (char *)"Destruct JupyROOTExecutorHandler"}, - {(char *)"CPyCppyyRegisterConverterAlias", (PyCFunction)PyROOT::RegisterConverterAlias, METH_VARARGS, - (char *)"Register a custom converter that is a reference to an existing converter"}, - {(char *)"CPyCppyyRegisterExecutorAlias", (PyCFunction)PyROOT::RegisterExecutorAlias, METH_VARARGS, - (char *)"Register a custom executor that is a reference to an existing executor"}, - {(char *)"PyObjRefCounterAsStdAny", (PyCFunction)PyROOT::PyObjRefCounterAsStdAny, METH_VARARGS, - (char *)"Wrap a reference count to any Python object in a std::any for resource management in C++"}, + {"AddCPPInstancePickling", (PyCFunction)PyROOT::AddCPPInstancePickling, METH_NOARGS, + "Add a custom pickling mechanism for Cppyy Python proxy objects"}, + {"GetBranchAttr", (PyCFunction)PyROOT::GetBranchAttr, METH_VARARGS, + "Allow to access branches as tree attributes"}, + {"AddTClassDynamicCastPyz", (PyCFunction)PyROOT::AddTClassDynamicCastPyz, METH_VARARGS, + "Cast the void* returned by TClass::DynamicCast to the right type"}, + {"BranchPyz", (PyCFunction)PyROOT::BranchPyz, METH_VARARGS, + "Fully enable the use of TTree::Branch from Python"}, + {"AddPrettyPrintingPyz", (PyCFunction)PyROOT::AddPrettyPrintingPyz, METH_VARARGS, + "Add pretty printing pythonization"}, + {"InitApplication", (PyCFunction)PyROOT::RPyROOTApplication::InitApplication, METH_VARARGS, + "Initialize interactive ROOT use from Python"}, + {"InstallGUIEventInputHook", (PyCFunction)PyROOT::RPyROOTApplication::InstallGUIEventInputHook, METH_NOARGS, + "Install an input hook to process GUI events"}, + {"_CPPInstance__expand__", (PyCFunction)PyROOT::CPPInstanceExpand, METH_VARARGS, + "Deserialize a pickled object"}, + {"JupyROOTExecutor", (PyCFunction)JupyROOTExecutor, METH_VARARGS, "Create JupyROOTExecutor"}, + {"JupyROOTDeclarer", (PyCFunction)JupyROOTDeclarer, METH_VARARGS, "Create JupyROOTDeclarer"}, + {"JupyROOTExecutorHandler_Clear", (PyCFunction)JupyROOTExecutorHandler_Clear, METH_NOARGS, + "Clear JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_Ctor", (PyCFunction)JupyROOTExecutorHandler_Ctor, METH_NOARGS, + "Create JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_Poll", (PyCFunction)JupyROOTExecutorHandler_Poll, METH_NOARGS, + "Poll JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_EndCapture", (PyCFunction)JupyROOTExecutorHandler_EndCapture, METH_NOARGS, + "End capture JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_InitCapture", (PyCFunction)JupyROOTExecutorHandler_InitCapture, METH_NOARGS, + "Init capture JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_GetStdout", (PyCFunction)JupyROOTExecutorHandler_GetStdout, METH_NOARGS, + "Get stdout JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_GetStderr", (PyCFunction)JupyROOTExecutorHandler_GetStderr, METH_NOARGS, + "Get stderr JupyROOTExecutorHandler"}, + {"JupyROOTExecutorHandler_Dtor", (PyCFunction)JupyROOTExecutorHandler_Dtor, METH_NOARGS, + "Destruct JupyROOTExecutorHandler"}, + {"CPyCppyyRegisterConverterAlias", (PyCFunction)PyROOT::RegisterConverterAlias, METH_VARARGS, + "Register a custom converter that is a reference to an existing converter"}, + {"CPyCppyyRegisterExecutorAlias", (PyCFunction)PyROOT::RegisterExecutorAlias, METH_VARARGS, + "Register a custom executor that is a reference to an existing executor"}, + {"PyObjRefCounterAsStdAny", (PyCFunction)PyROOT::PyObjRefCounterAsStdAny, METH_VARARGS, + "Wrap a reference count to any Python object in a std::any for resource management in C++"}, {NULL, NULL, 0, NULL}}; struct module_state { diff --git a/bindings/pyroot/pythonizations/src/PyROOTPythonize.h b/bindings/pyroot/pythonizations/src/PyROOTPythonize.h index 3034f851ba9d0..aec7ed708b3f9 100644 --- a/bindings/pyroot/pythonizations/src/PyROOTPythonize.h +++ b/bindings/pyroot/pythonizations/src/PyROOTPythonize.h @@ -12,7 +12,7 @@ #ifndef PYROOT_PYTHONIZE_H #define PYROOT_PYTHONIZE_H -#include "Python.h" +#include namespace PyROOT { diff --git a/bindings/pyroot/pythonizations/src/RPyROOTApplication.cxx b/bindings/pyroot/pythonizations/src/RPyROOTApplication.cxx index 2a07320e974e6..2808b2856f47d 100644 --- a/bindings/pyroot/pythonizations/src/RPyROOTApplication.cxx +++ b/bindings/pyroot/pythonizations/src/RPyROOTApplication.cxx @@ -10,7 +10,7 @@ *************************************************************************/ // Bindings -#include "Python.h" +#include #include "RPyROOTApplication.h" // ROOT @@ -51,18 +51,24 @@ bool PyROOT::RPyROOTApplication::CreateApplication(int ignoreCmdLineOpts) // Retrieve sys.argv list from Python PyObject *argl = PySys_GetObject("argv"); - if (argl && 0 < PyList_Size(argl)) - argc = (int)PyList_GET_SIZE(argl); + if (argl) { + Py_ssize_t size = PyList_Size(argl); + if (size > 0) + argc = static_cast(size); + } argv = new char *[argc]; + for (int i = 1; i < argc; ++i) { - char *argi = const_cast(PyUnicode_AsUTF8(PyList_GET_ITEM(argl, i))); + PyObject *item = PyList_GetItem(argl, i); + const char *argi = PyUnicode_AsUTF8AndSize(item, nullptr); + if (strcmp(argi, "-") == 0 || strcmp(argi, "--") == 0) { // Stop collecting options, the remaining are for the Python script argc = i; // includes program name break; } - argv[i] = argi; + argv[i] = const_cast(argi); } } @@ -139,7 +145,7 @@ void PyROOT::RPyROOTApplication::InitROOTMessageCallback() /// \param[in] args [0] Boolean that tells whether to ignore the command line options. PyObject *PyROOT::RPyROOTApplication::InitApplication(PyObject * /*self*/, PyObject *args) { - int argc = PyTuple_GET_SIZE(args); + int argc = PyTuple_Size(args); if (argc == 1) { PyObject *ignoreCmdLineOpts = PyTuple_GetItem(args, 0); diff --git a/bindings/pyroot/pythonizations/src/TClassPyz.cxx b/bindings/pyroot/pythonizations/src/TClassPyz.cxx index 426fabf378826..61a21d69616f2 100644 --- a/bindings/pyroot/pythonizations/src/TClassPyz.cxx +++ b/bindings/pyroot/pythonizations/src/TClassPyz.cxx @@ -12,8 +12,7 @@ // Bindings #include "CPyCppyy/API.h" -#include "../../cppyy/CPyCppyy/src/CPyCppyy.h" -#include "../../cppyy/CPyCppyy/src/CPPInstance.h" +#include "../../cppyy/CPyCppyy/src/Cppyy.h" #include "../../cppyy/CPyCppyy/src/Utility.h" #include "PyROOTPythonize.h" @@ -23,6 +22,10 @@ using namespace CPyCppyy; +namespace PyROOT{ +void GetBuffer(PyObject *pyobject, void *&buf); +} + // Cast the void* returned by TClass::DynamicCast to the right type PyObject *TClassDynamicCastPyz(PyObject *self, PyObject *args) { @@ -30,9 +33,26 @@ PyObject *TClassDynamicCastPyz(PyObject *self, PyObject *args) PyObject *pyclass = nullptr; PyObject *pyobject = nullptr; int up = 1; - if (!PyArg_ParseTuple(args, "O!O|i:DynamicCast", &CPPInstance_Type, &pyclass, &pyobject, &up)) + if (!PyArg_ParseTuple(args, "OO|i:DynamicCast", &pyclass, &pyobject, &up)) return nullptr; + if (!CPyCppyy::Instance_Check(pyclass)) { + PyObject *type = PyObject_Type(pyclass); + if (!type) { + return nullptr; + } + PyObject *name = PyObject_Str(type); + Py_DecRef(type); + const char *nameStr = name ? PyUnicode_AsUTF8AndSize(name, nullptr) : nullptr; + if (nameStr) { + PyErr_Format(PyExc_TypeError, "DynamicCast argument 1 must be a cppyy instance, got '%s'", nameStr); + } else { + PyErr_SetString(PyExc_TypeError, "DynamicCast argument 1 must be a cppyy instance"); + } + Py_DecRef(name); + return nullptr; + } + // Perform actual cast - calls default implementation of DynamicCast TClass *cl1 = (TClass *)CPyCppyy::Instance_AsVoidPtr(self); TClass *cl2 = (TClass *)CPyCppyy::Instance_AsVoidPtr(pyclass); @@ -41,16 +61,19 @@ PyObject *TClassDynamicCastPyz(PyObject *self, PyObject *args) if (CPyCppyy::Instance_Check(pyobject)) { address = CPyCppyy::Instance_AsVoidPtr(pyobject); - } else if (PyInt_Check(pyobject) || PyLong_Check(pyobject)) { - address = (void *)PyLong_AsLongLong(pyobject); } else { - Utility::GetBuffer(pyobject, '*', 1, address, false); + long long value = PyLong_AsLongLong(pyobject); + if (!PyErr_Occurred()) { + address = (void *)value; // pyobject was indeed a PyLong + } else { + PyErr_Clear(); + PyROOT::GetBuffer(pyobject, address); + } } // Now use binding to return a usable class. Upcast: result is a base. // Downcast: result is a derived. - Cppyy::TCppType_t cpptype = ((CPyCppyy::CPPInstance *)(up ? pyclass : self))->ObjectIsA(); - TClass *tcl = TClass::GetClass(Cppyy::GetScopedFinalName(cpptype).c_str()); + TClass *tcl = TClass::GetClass(CPyCppyy::Instance_GetScopedFinalName(up ? pyclass : self).c_str()); TClass *klass = (TClass *)tcl->DynamicCast(TClass::Class(), up ? CPyCppyy::Instance_AsVoidPtr(pyclass) : cl1); return CPyCppyy::Instance_FromVoidPtr(address, klass->GetName()); diff --git a/bindings/pyroot/pythonizations/src/TPyDispatcher.cxx b/bindings/pyroot/pythonizations/src/TPyDispatcher.cxx index bdb01d04eafa4..fa5ba950528f9 100644 --- a/bindings/pyroot/pythonizations/src/TPyDispatcher.cxx +++ b/bindings/pyroot/pythonizations/src/TPyDispatcher.cxx @@ -54,7 +54,7 @@ TPyDispatcher &TPyDispatcher::operator=(const TPyDispatcher &other) if (this != &other) { this->TObject::operator=(other); - Py_XDECREF(fCallable); + Py_DecRef(fCallable); Py_XINCREF(other.fCallable); fCallable = other.fCallable; } @@ -67,7 +67,7 @@ TPyDispatcher &TPyDispatcher::operator=(const TPyDispatcher &other) TPyDispatcher::~TPyDispatcher() { - Py_XDECREF(fCallable); + Py_DecRef(fCallable); } //- public members ----------------------------------------------------------- @@ -93,13 +93,13 @@ PyObject *TPyDispatcher::DispatchVA(const char *format, ...) if (!PyTuple_Check(args)) { // if only one arg ... PyObject *t = PyTuple_New(1); - PyTuple_SET_ITEM(t, 0, args); + PyTuple_SetItem(t, 0, args); args = t; } } PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); @@ -136,27 +136,27 @@ PyObject *TPyDispatcher::DispatchVA1(const char *clname, void *obj, const char * if (!PyTuple_Check(args)) { // if only one arg ... PyObject *t = PyTuple_New(2); - PyTuple_SET_ITEM(t, 0, pyobj); - PyTuple_SET_ITEM(t, 1, args); + PyTuple_SetItem(t, 0, pyobj); + PyTuple_SetItem(t, 1, args); args = t; } else { - PyObject *t = PyTuple_New(PyTuple_GET_SIZE(args) + 1); - PyTuple_SET_ITEM(t, 0, pyobj); - for (int i = 0; i < PyTuple_GET_SIZE(args); i++) { - PyObject *item = PyTuple_GET_ITEM(args, i); - Py_INCREF(item); - PyTuple_SET_ITEM(t, i + 1, item); + PyObject *t = PyTuple_New(PyTuple_Size(args) + 1); + PyTuple_SetItem(t, 0, pyobj); + for (int i = 0; i < PyTuple_Size(args); i++) { + PyObject *item = PyTuple_GetItem(args, i); + Py_IncRef(item); + PyTuple_SetItem(t, i + 1, item); } - Py_DECREF(args); + Py_DecRef(args); args = t; } } else { args = PyTuple_New(1); - PyTuple_SET_ITEM(args, 0, pyobj); + PyTuple_SetItem(args, 0, pyobj); } PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); @@ -171,12 +171,12 @@ PyObject *TPyDispatcher::DispatchVA1(const char *clname, void *obj, const char * PyObject *TPyDispatcher::Dispatch(TPad *selpad, TObject *selected, Int_t event) { PyObject *args = PyTuple_New(3); - PyTuple_SET_ITEM(args, 0, CPyCppyy::Instance_FromVoidPtr(selpad, "TPad")); - PyTuple_SET_ITEM(args, 1, CPyCppyy::Instance_FromVoidPtr(selected, "TObject")); - PyTuple_SET_ITEM(args, 2, PyLong_FromLong(event)); + PyTuple_SetItem(args, 0, CPyCppyy::Instance_FromVoidPtr(selpad, "TPad")); + PyTuple_SetItem(args, 1, CPyCppyy::Instance_FromVoidPtr(selected, "TObject")); + PyTuple_SetItem(args, 2, PyLong_FromLong(event)); PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); @@ -191,13 +191,13 @@ PyObject *TPyDispatcher::Dispatch(TPad *selpad, TObject *selected, Int_t event) PyObject *TPyDispatcher::Dispatch(Int_t event, Int_t x, Int_t y, TObject *selected) { PyObject *args = PyTuple_New(4); - PyTuple_SET_ITEM(args, 0, PyLong_FromLong(event)); - PyTuple_SET_ITEM(args, 1, PyLong_FromLong(x)); - PyTuple_SET_ITEM(args, 2, PyLong_FromLong(y)); - PyTuple_SET_ITEM(args, 3, CPyCppyy::Instance_FromVoidPtr(selected, "TObject")); + PyTuple_SetItem(args, 0, PyLong_FromLong(event)); + PyTuple_SetItem(args, 1, PyLong_FromLong(x)); + PyTuple_SetItem(args, 2, PyLong_FromLong(y)); + PyTuple_SetItem(args, 3, CPyCppyy::Instance_FromVoidPtr(selected, "TObject")); PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); @@ -212,12 +212,12 @@ PyObject *TPyDispatcher::Dispatch(Int_t event, Int_t x, Int_t y, TObject *select PyObject *TPyDispatcher::Dispatch(TVirtualPad *pad, TObject *obj, Int_t event) { PyObject *args = PyTuple_New(3); - PyTuple_SET_ITEM(args, 0, CPyCppyy::Instance_FromVoidPtr(pad, "TVirtualPad")); - PyTuple_SET_ITEM(args, 1, CPyCppyy::Instance_FromVoidPtr(obj, "TObject")); - PyTuple_SET_ITEM(args, 2, PyLong_FromLong(event)); + PyTuple_SetItem(args, 0, CPyCppyy::Instance_FromVoidPtr(pad, "TVirtualPad")); + PyTuple_SetItem(args, 1, CPyCppyy::Instance_FromVoidPtr(obj, "TObject")); + PyTuple_SetItem(args, 2, PyLong_FromLong(event)); PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); @@ -232,11 +232,11 @@ PyObject *TPyDispatcher::Dispatch(TVirtualPad *pad, TObject *obj, Int_t event) PyObject *TPyDispatcher::Dispatch(TGListTreeItem *item, TDNDData *data) { PyObject *args = PyTuple_New(2); - PyTuple_SET_ITEM(args, 0, CPyCppyy::Instance_FromVoidPtr(item, "TGListTreeItem")); - PyTuple_SET_ITEM(args, 1, CPyCppyy::Instance_FromVoidPtr(data, "TDNDData")); + PyTuple_SetItem(args, 0, CPyCppyy::Instance_FromVoidPtr(item, "TGListTreeItem")); + PyTuple_SetItem(args, 1, CPyCppyy::Instance_FromVoidPtr(data, "TDNDData")); PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); @@ -251,11 +251,11 @@ PyObject *TPyDispatcher::Dispatch(TGListTreeItem *item, TDNDData *data) PyObject *TPyDispatcher::Dispatch(const char *name, const TList *attr) { PyObject *args = PyTuple_New(2); - PyTuple_SET_ITEM(args, 0, PyBytes_FromString(name)); - PyTuple_SET_ITEM(args, 1, CPyCppyy::Instance_FromVoidPtr((void *)attr, "TList")); + PyTuple_SetItem(args, 0, PyBytes_FromString(name)); + PyTuple_SetItem(args, 1, CPyCppyy::Instance_FromVoidPtr((void *)attr, "TList")); PyObject *result = PyObject_CallObject(fCallable, args); - Py_XDECREF(args); + Py_DecRef(args); if (!result) { PyErr_Print(); diff --git a/bindings/pyroot/pythonizations/src/TTreePyz.cxx b/bindings/pyroot/pythonizations/src/TTreePyz.cxx index fa96c3f672d7c..480e8a55d19e3 100644 --- a/bindings/pyroot/pythonizations/src/TTreePyz.cxx +++ b/bindings/pyroot/pythonizations/src/TTreePyz.cxx @@ -10,10 +10,17 @@ *************************************************************************/ // Bindings -#include "../../cppyy/CPyCppyy/src/CPyCppyy.h" +#include + +// TODO: refactor public CPyCppyy API such that this forward declaration is not +// needed anymore. Including "CPyCppyy/API.h" should be enough. +namespace CPyCppyy { +typedef Py_ssize_t dim_t; +} // namespace CPyCppyy + +#include "../../cppyy/CPyCppyy/src/Cppyy.h" #include "../../cppyy/CPyCppyy/src/CPPInstance.h" #include "../../cppyy/CPyCppyy/src/ProxyWrappers.h" -#include "../../cppyy/CPyCppyy/src/Utility.h" #include "../../cppyy/CPyCppyy/src/Dimensions.h" #include "CPyCppyy/API.h" @@ -38,15 +45,19 @@ namespace { // Get the TClass of the C++ object proxied by pyobj -TClass *GetTClass(const PyObject *pyobj) +TClass *GetTClass(PyObject *pyobj) { - return TClass::GetClass(Cppyy::GetScopedFinalName(((CPyCppyy::CPPInstance *)pyobj)->ObjectIsA()).c_str()); + return TClass::GetClass(CPyCppyy::Instance_GetScopedFinalName(pyobj).c_str()); } } // namespace using namespace CPyCppyy; +namespace PyROOT{ +void GetBuffer(PyObject *pyobject, void *&buf); +} + static TBranch *SearchForBranch(TTree *tree, const char *name) { TBranch *branch = tree->GetBranch(name); @@ -180,9 +191,9 @@ PyObject *PyROOT::GetBranchAttr(PyObject * /*self*/, PyObject *args) PyArg_ParseTuple(args, "OU:GetBranchAttr", &self, &pyname); - const char *name_possibly_alias = PyUnicode_AsUTF8(pyname); + const char *name_possibly_alias = PyUnicode_AsUTF8AndSize(pyname, nullptr); if (!name_possibly_alias) - return 0; + return nullptr; // get hold of actual tree auto tree = (TTree *)GetTClass(self)->DynamicCast(TTree::Class(), CPyCppyy::Instance_AsVoidPtr(self)); @@ -205,8 +216,8 @@ PyObject *PyROOT::GetBranchAttr(PyObject * /*self*/, PyObject *args) const auto [finalAddressVoidPtr, finalTypeName] = ResolveBranch(tree, name, branch); if (!finalTypeName.empty()) { PyObject *outTuple = PyTuple_New(2); - PyTuple_SET_ITEM(outTuple, 0, PyLong_FromLongLong((intptr_t)finalAddressVoidPtr)); - PyTuple_SET_ITEM(outTuple, 1, CPyCppyy_PyText_FromString((finalTypeName + "*").c_str())); + PyTuple_SetItem(outTuple, 0, PyLong_FromLongLong((intptr_t)finalAddressVoidPtr)); + PyTuple_SetItem(outTuple, 1, PyUnicode_FromString((finalTypeName + "*").c_str())); return outTuple; } } @@ -217,8 +228,8 @@ PyObject *PyROOT::GetBranchAttr(PyObject * /*self*/, PyObject *args) auto wrapper = WrapLeaf(leaf); if (wrapper != nullptr) { PyObject *outTuple = PyTuple_New(2); - PyTuple_SET_ITEM(outTuple, 0, wrapper); - PyTuple_SET_ITEM(outTuple, 1, CPyCppyy_PyText_FromString("")); + PyTuple_SetItem(outTuple, 0, wrapper); + PyTuple_SetItem(outTuple, 1, PyUnicode_FromString("")); return outTuple; } } @@ -239,7 +250,7 @@ PyObject *TryBranchLeafListOverload(int argc, PyObject *args) PyObject *name = nullptr, *address = nullptr, *leaflist = nullptr, *bufsize = nullptr; if (PyArg_ParseTuple(args, "OO!OO!|O!:Branch", &treeObj, &PyUnicode_Type, &name, &address, &PyUnicode_Type, - &leaflist, &PyInt_Type, &bufsize)) { + &leaflist, &PyLong_Type, &bufsize)) { auto tree = (TTree *)GetTClass(treeObj)->DynamicCast(TTree::Class(), CPyCppyy::Instance_AsVoidPtr(treeObj)); if (!tree) { @@ -248,17 +259,25 @@ PyObject *TryBranchLeafListOverload(int argc, PyObject *args) } void *buf = nullptr; - if (CPPInstance_Check(address)) + if (CPyCppyy::Instance_Check(address)) buf = CPyCppyy::Instance_AsVoidPtr(address); else - Utility::GetBuffer(address, '*', 1, buf, false); + PyROOT::GetBuffer(address, buf); if (buf) { TBranch *branch = nullptr; + const char *nameString = PyUnicode_AsUTF8AndSize(name, nullptr); + if (!nameString) { + return nullptr; + } + const char *leaflistString = PyUnicode_AsUTF8AndSize(leaflist, nullptr); + if (!leaflistString) { + return nullptr; + } if (argc == 5) { - branch = tree->Branch(PyUnicode_AsUTF8(name), buf, PyUnicode_AsUTF8(leaflist), PyInt_AS_LONG(bufsize)); + branch = tree->Branch(nameString, buf, leaflistString, PyLong_AsLong(bufsize)); } else { - branch = tree->Branch(PyUnicode_AsUTF8(name), buf, PyUnicode_AsUTF8(leaflist)); + branch = tree->Branch(nameString, buf, leaflistString); } return BindCppObject(branch, Cppyy::GetScope("TBranch")); @@ -283,12 +302,12 @@ PyObject *TryBranchPtrToPtrOverloads(int argc, PyObject *args) auto bIsMatch = false; if (PyArg_ParseTuple(args, "OO!O!O|O!O!:Branch", &treeObj, &PyUnicode_Type, &name, &PyUnicode_Type, &clName, - &address, &PyInt_Type, &bufsize, &PyInt_Type, &splitlevel)) { + &address, &PyLong_Type, &bufsize, &PyLong_Type, &splitlevel)) { bIsMatch = true; } else { PyErr_Clear(); - if (PyArg_ParseTuple(args, "OO!O|O!O!", &treeObj, &PyUnicode_Type, &name, &address, &PyInt_Type, &bufsize, - &PyInt_Type, &splitlevel)) { + if (PyArg_ParseTuple(args, "OO!O|O!O!", &treeObj, &PyUnicode_Type, &name, &address, &PyLong_Type, &bufsize, + &PyLong_Type, &splitlevel)) { bIsMatch = true; } else { PyErr_Clear(); @@ -302,10 +321,17 @@ PyObject *TryBranchPtrToPtrOverloads(int argc, PyObject *args) return nullptr; } - std::string klName = clName ? PyUnicode_AsUTF8(clName) : ""; + std::string klName; + if (clName) { + const char *clNameString = PyUnicode_AsUTF8AndSize(clName, nullptr); + if (!clNameString) { + return nullptr; + } + klName = clNameString; + } void *buf = nullptr; - if (CPPInstance_Check(address)) { + if (CPyCppyy::Instance_Check(address)) { if (((CPPInstance *)address)->fFlags & CPPInstance::kIsReference) buf = (void *)((CPPInstance *)address)->fObject; else @@ -316,18 +342,25 @@ PyObject *TryBranchPtrToPtrOverloads(int argc, PyObject *args) argc += 1; } } else { - Utility::GetBuffer(address, '*', 1, buf, false); + PyROOT::GetBuffer(address, buf); } if (buf && !klName.empty()) { TBranch *branch = nullptr; + const char *nameString = nullptr; + if (argc == 4 || argc == 5 || argc == 6) { + nameString = PyUnicode_AsUTF8AndSize(name, nullptr); + if (!nameString) { + return nullptr; + } + } if (argc == 4) { - branch = tree->Branch(PyUnicode_AsUTF8(name), klName.c_str(), buf); + branch = tree->Branch(nameString, klName.c_str(), buf); } else if (argc == 5) { - branch = tree->Branch(PyUnicode_AsUTF8(name), klName.c_str(), buf, PyInt_AS_LONG(bufsize)); + branch = tree->Branch(nameString, klName.c_str(), buf, PyLong_AsLong(bufsize)); } else if (argc == 6) { - branch = tree->Branch(PyUnicode_AsUTF8(name), klName.c_str(), buf, PyInt_AS_LONG(bufsize), - PyInt_AS_LONG(splitlevel)); + branch = tree->Branch(nameString, klName.c_str(), buf, PyLong_AsLong(bufsize), + PyLong_AsLong(splitlevel)); } return BindCppObject(branch, Cppyy::GetScope("TBranch")); @@ -359,7 +392,7 @@ PyObject *TryBranchPtrToPtrOverloads(int argc, PyObject *args) /// - ( const char*, T**, Int_t = 32000, Int_t = 99 ) PyObject *PyROOT::BranchPyz(PyObject * /* self */, PyObject *args) { - int argc = PyTuple_GET_SIZE(args); + int argc = PyTuple_Size(args); if (argc >= 3) { // We count the TTree proxy object too auto branch = TryBranchLeafListOverload(argc, args); diff --git a/bindings/pyroot/pythonizations/test/generate_keras_functional.py b/bindings/pyroot/pythonizations/test/generate_keras_functional.py index 11f7bdefda00e..35fd5e6260128 100644 --- a/bindings/pyroot/pythonizations/test/generate_keras_functional.py +++ b/bindings/pyroot/pythonizations/test/generate_keras_functional.py @@ -1,6 +1,9 @@ +import warnings + def generate_keras_functional(dst_dir): import numpy as np + import keras from keras import layers, models from parser_test_function import is_channels_first_supported @@ -16,8 +19,14 @@ def train_and_save(model, name): model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae']) model.summary() - model.fit(x_train, y_train, epochs=1, verbose=0) - model.save(f"{dst_dir}/Functional_{name}_test.keras") + if len(model.trainable_weights) > 0: + model.fit(x_train, y_train, epochs=1, verbose=0) + + with warnings.catch_warnings(): + # Some object inside TensorFlow/Keras has an outdated __array__ implementation + warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*__array__.*copy keyword.*") + model.save(f"{dst_dir}/Functional_{name}_test.keras") + print("generated and saved functional model",name) @@ -211,7 +220,11 @@ def train_and_save(model, name): sub = layers.Subtract()([d1, d2]) mul = layers.Multiply()([d1, d2]) merged = layers.Concatenate()([add, sub, mul]) - merged = layers.LeakyReLU(alpha=0.1)(merged) + # `alpha` was renamed to `negative_slope` in Keras 3 + if keras.__version__ >= "3.0": + merged = layers.LeakyReLU(negative_slope=0.1)(merged) + else: + merged = layers.LeakyReLU(alpha=0.1)(merged) out = layers.Dense(4, activation="softmax")(merged) model = models.Model([inp1, inp2], out) train_and_save(model, "Layer_Combination_3") diff --git a/bindings/pyroot/pythonizations/test/generate_keras_sequential.py b/bindings/pyroot/pythonizations/test/generate_keras_sequential.py index 40b6c645b1fd4..47d10968b8ca5 100644 --- a/bindings/pyroot/pythonizations/test/generate_keras_sequential.py +++ b/bindings/pyroot/pythonizations/test/generate_keras_sequential.py @@ -1,5 +1,8 @@ +import warnings + def generate_keras_sequential(dst_dir): + import keras import numpy as np from keras import layers, models from parser_test_function import is_channels_first_supported @@ -9,10 +12,15 @@ def train_and_save(model, name): x_train = np.random.rand(32, *model.input_shape[1:]) y_train = np.random.rand(32, *model.output_shape[1:]) model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae']) - model.fit(x_train, y_train, epochs=1, verbose=0) + if len(model.trainable_weights) > 0: + model.fit(x_train, y_train, epochs=1, verbose=0) model.summary() print("fitting sequential model",name) - model.save(f"{dst_dir}/Sequential_{name}_test.keras") + + with warnings.catch_warnings(): + # Some object inside TensorFlow/Keras has an outdated __array__ implementation + warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*__array__.*copy keyword.*") + model.save(f"{dst_dir}/Sequential_{name}_test.keras") # Binary Ops: Add, Subtract, Multiply are not typical in Sequential - skipping those @@ -183,6 +191,9 @@ def train_and_save(model, name): ]) train_and_save(modelA, "Layer_Combination_1") + # `alpha` was renamed to `negative_slope` in Keras 3 + negative_slope_key = "negative_slope" if keras.__version__ >= "3.0" else "alpha" + modelB = models.Sequential([ layers.Input(shape=(32,32,3)), layers.Conv2D(8, (3,3), padding='valid', data_format='channels_last', activation='relu'), @@ -193,7 +204,7 @@ def train_and_save(model, name): layers.Permute((2, 1)), layers.Flatten(), layers.Dense(32), - layers.LeakyReLU(alpha=0.1), + layers.LeakyReLU(**{negative_slope_key : 0.1}), layers.Dense(10, activation='softmax'), ]) train_and_save(modelB, "Layer_Combination_2") @@ -210,4 +221,4 @@ def train_and_save(model, name): layers.Dense(8, activation='swish'), layers.Dense(3, activation='softmax'), ]) - train_and_save(modelC, "Layer_Combination_3") \ No newline at end of file + train_and_save(modelC, "Layer_Combination_3") diff --git a/bindings/pyroot/pythonizations/test/ml_dataloader.py b/bindings/pyroot/pythonizations/test/ml_dataloader.py index 40ffa0197c8b9..398b32df15d12 100644 --- a/bindings/pyroot/pythonizations/test/ml_dataloader.py +++ b/bindings/pyroot/pythonizations/test/ml_dataloader.py @@ -4725,7 +4725,7 @@ def test14_big_data_replacement_true(self): # max samling strategy to guarantee duplicate sampled entires max_sampling_ratio = entries_in_rdf_minor / entries_in_rdf_major - sampling_ratio = round(uniform(0.01, max_sampling_ratio), 2) + sampling_ratio = round(uniform(0.01, max_sampling_ratio - 0.01), 2) error_message = f"\n Batch size: {batch_size}\ Number of major entries: {entries_in_rdf_major} \ diff --git a/bindings/pyroot/pythonizations/test/parser_test_function.py b/bindings/pyroot/pythonizations/test/parser_test_function.py index eaa4a0ed5fb2f..9232362ed45ba 100644 --- a/bindings/pyroot/pythonizations/test/parser_test_function.py +++ b/bindings/pyroot/pythonizations/test/parser_test_function.py @@ -2,10 +2,6 @@ ''' The test file contains two types of functions: - is_accurate: - - This function checks whether the inference results from SOFIE and Keras are accurate within a specified - tolerance. Since the inference result from Keras is not flattened, the function flattens both tensors before - performing the comparison. generate_and_test_inference: - This function accepts the following inputs: @@ -29,7 +25,7 @@ shape from the model object. - Convert the inference results to NumPy arrays: The SOFIE result is of type vector, and the Keras result is a TensorFlow tensor. Both are converted to - NumPy arrays before being passed to the is_accurate function for comparison. + NumPy arrays before being passed to the np.testing.assert_allclose function for comparison. ''' def is_channels_first_supported() : @@ -42,16 +38,6 @@ def is_channels_first_supported() : return True -def is_accurate(tensor_a, tensor_b, tolerance=1e-2): - tensor_a = tensor_a.flatten() - tensor_b = tensor_b.flatten() - for i in range(len(tensor_a)): - difference = abs(tensor_a[i] - tensor_b[i]) - if difference > tolerance: - print(tensor_a[i], tensor_b[i]) - return False - return True - def generate_and_test_inference(model_file_path: str, generated_header_file_dir: str = None, batch_size=1): import keras @@ -81,7 +67,6 @@ def generate_and_test_inference(model_file_path: str, generated_header_file_dir: sofie_model_namespace = getattr(ROOT, "TMVA_SOFIE_" + model_name) inference_session = sofie_model_namespace.Session(generated_header_file_path.removesuffix(".hxx") + ".dat") keras_model = keras.models.load_model(model_file_path) - keras_model.load_weights(model_file_path) input_tensors = [] for model_input in keras_model.inputs: @@ -91,11 +76,17 @@ def generate_and_test_inference(model_file_path: str, generated_header_file_dir: sofie_inference_result = inference_session.infer(*input_tensors) sofie_output_tensor_shape = list(rmodel.GetTensorShape(rmodel.GetOutputTensorNames()[0])) # get output shape # from SOFIE - keras_inference_result = keras_model(input_tensors) + # Keras explicitly forbids input tensor lists of size 1 + if len(keras_model.inputs) == 1: + keras_inference_result = keras_model(input_tensors[0]) + else: + keras_inference_result = keras_model(input_tensors) if sofie_output_tensor_shape != list(keras_inference_result.shape): raise AssertionError("Output tensor dimensions from SOFIE and Keras do not match") - sofie_inference_result = np.asarray(sofie_inference_result) - keras_inference_result = np.asarray(keras_inference_result) - is_inference_accurate = is_accurate(sofie_inference_result, keras_inference_result) - if not is_inference_accurate: - raise AssertionError("Inference results from SOFIE and Keras do not match") \ No newline at end of file + + np.testing.assert_allclose( + np.asarray(sofie_inference_result).flatten(), + np.asarray(keras_inference_result).flatten(), + atol=1e-2, + rtol=0. # explicitly disable relative tolerance (NumPy uses |a - b| <= atol + rtol * |b|) + ) diff --git a/bindings/pyroot/pythonizations/test/root_module.py b/bindings/pyroot/pythonizations/test/root_module.py index ec1e8230ddd3d..caf91b0e5a656 100644 --- a/bindings/pyroot/pythonizations/test/root_module.py +++ b/bindings/pyroot/pythonizations/test/root_module.py @@ -126,6 +126,35 @@ def test_deprecated_features(self): ROOT.SetHeuristicMemoryPolicy(True) ROOT.SetHeuristicMemoryPolicy(False) + def test_lazy_gdirectory(self): + """Check that gDirectory is always lazy evaluated to the current + directory. + + Reproducer for GitHub issue + https://github.com/root-project/root/issues/21693 + """ + import ROOT + + # Should be gROOT initially + self.assertEqual(ROOT.gDirectory, ROOT.gROOT) + + gDirectory_1 = ROOT.gDirectory + + f = ROOT.TFile("Hybrid.root", "RECREATE") + f.cd() + + gDirectory_2 = ROOT.gDirectory + + # Now, both gDirectory_1 and _2 should resolve to the current TFile + # directory, no matter when the adapters were created. + self.assertEqual(gDirectory_1, gDirectory_2) + self.assertNotEqual(gDirectory_1, ROOT.gROOT) + + # If we re-assign the gDirectory now, it should be considered + ROOT.gDirectory = ROOT.nullptr + self.assertEqual(gDirectory_1, ROOT.nullptr) + self.assertEqual(gDirectory_2, ROOT.nullptr) + if __name__ == "__main__": unittest.main() diff --git a/bindings/pyroot/pythonizations/test/tcontext_contextmanager.py b/bindings/pyroot/pythonizations/test/tcontext_contextmanager.py index 4cea01437a063..b442055ec746e 100644 --- a/bindings/pyroot/pythonizations/test/tcontext_contextmanager.py +++ b/bindings/pyroot/pythonizations/test/tcontext_contextmanager.py @@ -16,15 +16,15 @@ def default_constructor(self): Check status of gDirectory with default constructor. """ filename = "TContextContextManager_test_default_constructor.root" - self.assertIs(ROOT.gDirectory, ROOT.gROOT) + self.assertEqual(ROOT.gDirectory, ROOT.gROOT) with TDirectory.TContext(): # Create a file to change gDirectory testfile = ROOT.TFile(filename, "recreate") - self.assertIs(ROOT.gDirectory, testfile) + self.assertEqual(ROOT.gDirectory, testfile) testfile.Close() - self.assertIs(ROOT.gDirectory, ROOT.gROOT) + self.assertEqual(ROOT.gDirectory, ROOT.gROOT) os.remove(filename) def constructor_onearg(self): @@ -35,12 +35,12 @@ def constructor_onearg(self): file0 = ROOT.TFile(filenames[0], "recreate") file1 = ROOT.TFile(filenames[1], "recreate") - self.assertIs(ROOT.gDirectory, file1) + self.assertEqual(ROOT.gDirectory, file1) with TDirectory.TContext(file0): - self.assertIs(ROOT.gDirectory, file0) + self.assertEqual(ROOT.gDirectory, file0) - self.assertIs(ROOT.gDirectory, file1) + self.assertEqual(ROOT.gDirectory, file1) file0.Close() file1.Close() for filename in filenames: @@ -55,12 +55,12 @@ def constructor_twoargs(self): file0 = ROOT.TFile(filenames[0], "recreate") file1 = ROOT.TFile(filenames[1], "recreate") file2 = ROOT.TFile(filenames[2], "recreate") - self.assertIs(ROOT.gDirectory, file2) + self.assertEqual(ROOT.gDirectory, file2) with TDirectory.TContext(file0, file1): - self.assertIs(ROOT.gDirectory, file1) + self.assertEqual(ROOT.gDirectory, file1) - self.assertIs(ROOT.gDirectory, file0) + self.assertEqual(ROOT.gDirectory, file0) file0.Close() file1.Close() file2.Close() diff --git a/bindings/tpython/CMakeLists.txt b/bindings/tpython/CMakeLists.txt index cf6374818a673..c48b3250ffba8 100644 --- a/bindings/tpython/CMakeLists.txt +++ b/bindings/tpython/CMakeLists.txt @@ -30,4 +30,15 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTPython Python3::Python ) +# Use what is in the limited API since Python 3.10, if we build with a lower +# Python version, we don't bother using the limited API. +if (Python3_VERSION VERSION_GREATER_EQUAL "3.10") + # On Windows we can't use the stable ABI yet: it requires linking against a + # different libpython, so as long as we don't build all translation units in + # the ROOT Pythonization library with the stable ABI we should not use it. + if(NOT MSVC) + target_compile_options(ROOTTPython PRIVATE -DPy_LIMITED_API=0x030A0000) + endif() +endif() + ROOT_ADD_TEST_SUBDIRECTORY(test) diff --git a/bindings/tpython/src/TPyArg.cxx b/bindings/tpython/src/TPyArg.cxx index 09ed4f81b2faf..efb0a468fe605 100644 --- a/bindings/tpython/src/TPyArg.cxx +++ b/bindings/tpython/src/TPyArg.cxx @@ -10,7 +10,7 @@ // *************************************************************************/ // Bindings -#include "Python.h" +#include #include "TPyArg.h" @@ -42,7 +42,7 @@ void TPyArg::CallConstructor(PyObject *&pyself, PyObject *pyclass, const std::ve int nArgs = args.size(); PyObject *pyargs = PyTuple_New(nArgs); for (int i = 0; i < nArgs; ++i) - PyTuple_SET_ITEM(pyargs, i, (PyObject *)args[i]); + PyTuple_SetItem(pyargs, i, (PyObject *)args[i]); pyself = PyObject_Call(pyclass, pyargs, NULL); Py_DecRef(pyargs); } @@ -65,7 +65,7 @@ PyObject *TPyArg::CallMethod(PyObject *pymeth, const std::vector &args) int nArgs = args.size(); PyObject *pyargs = PyTuple_New(nArgs); for (int i = 0; i < nArgs; ++i) - PyTuple_SET_ITEM(pyargs, i, (PyObject *)args[i]); + PyTuple_SetItem(pyargs, i, (PyObject *)args[i]); PyObject *result = PyObject_Call(pymeth, pyargs, NULL); Py_DecRef(pyargs); return result; diff --git a/bindings/tpython/src/TPyClassGenerator.cxx b/bindings/tpython/src/TPyClassGenerator.cxx index 622820b6305ea..f95163a07e127 100644 --- a/bindings/tpython/src/TPyClassGenerator.cxx +++ b/bindings/tpython/src/TPyClassGenerator.cxx @@ -9,7 +9,7 @@ // * For the list of contributors see $ROOTSYS/README/CREDITS. * // *************************************************************************/ -#include "Python.h" +#include #include "TPyClassGenerator.h" #include "TPyReturn.h" @@ -26,14 +26,56 @@ #include namespace { - class PyGILRAII { - PyGILState_STATE m_GILState; - public: - PyGILRAII() : m_GILState(PyGILState_Ensure()) { } - ~PyGILRAII() { PyGILState_Release(m_GILState); } - }; + +class PyGILRAII { + PyGILState_STATE m_GILState; + +public: + PyGILRAII() : m_GILState(PyGILState_Ensure()) {} + ~PyGILRAII() { PyGILState_Release(m_GILState); } +}; + +#if (defined(Py_LIMITED_API) || PY_VERSION_HEX < 0x30d00f0) + +// Implementation of PyObject_GetOptionalAttr and +// PyObject_GetOptionalAttrString from +// https://github.com/python/pythoncapi-compat/, since the function is not part +// of the limited API. + +inline int PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result) +{ + *result = PyObject_GetAttr(obj, attr_name); + if (*result != NULL) { + return 1; + } + if (!PyErr_Occurred()) { + return 0; + } + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + return 0; + } + return -1; } +inline int PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result) +{ + PyObject *name_obj; + int rc; + name_obj = PyUnicode_FromString(attr_name); + if (name_obj == NULL) { + *result = NULL; + return -1; + } + rc = PyObject_GetOptionalAttr(obj, name_obj, result); + Py_DECREF(name_obj); + return rc; +} + +#endif + +} // namespace + //- public members ----------------------------------------------------------- TClass *TPyClassGenerator::GetClass(const char *name, Bool_t load) { @@ -75,26 +117,25 @@ TClass *TPyClassGenerator::GetClass(const char *name, Bool_t load, Bool_t silent PyObject *dct = PyModule_GetDict(mod); keys = PyDict_Keys(dct); - for (int i = 0; i < PyList_GET_SIZE(keys); ++i) { - PyObject *key = PyList_GET_ITEM(keys, i); - Py_IncRef(key); - + for (int i = 0; i < PyList_Size(keys); ++i) { + // borrowed references + PyObject *key = PyList_GetItem(keys, i); PyObject *attr = PyDict_GetItem(dct, key); - Py_IncRef(attr); // TODO: refactor the code below with the class method code if (PyCallable_Check(attr) && !(PyType_Check(attr) || PyObject_HasAttr(attr, bases))) { - std::string func_name = PyUnicode_AsUTF8(key); + const char *func_name = PyUnicode_AsUTF8AndSize(key, nullptr); + if (!func_name) { + Py_DecRef(keys); + Py_DecRef(bases); + return nullptr; // propagate possible error + } // figure out number of variables required -#if PY_VERSION_HEX < 0x30d00f0 - PyObject *func_code = PyObject_GetAttrString(attr, (char *)"func_code"); -#else PyObject *func_code = nullptr; PyObject_GetOptionalAttrString(attr, (char *)"func_code", &func_code); -#endif PyObject *var_names = func_code ? PyObject_GetAttrString(func_code, (char *)"co_varnames") : NULL; - int nVars = var_names ? PyTuple_GET_SIZE(var_names) : 0 /* TODO: probably large number, all default? */; + int nVars = var_names ? PyTuple_Size(var_names) : 0 /* TODO: probably large number, all default? */; if (nVars < 0) nVars = 0; Py_DecRef(var_names); @@ -116,9 +157,6 @@ TClass *TPyClassGenerator::GetClass(const char *name, Bool_t load, Bool_t silent // call dispatch (method or class pointer hard-wired) nsCode << " return TPyReturn(TPyArg::CallMethod((PyObject*)" << std::showbase << (uintptr_t)attr << ", v)); }\n"; } - - Py_DecRef(attr); - Py_DecRef(key); } Py_DecRef(keys); @@ -187,14 +225,18 @@ TClass *TPyClassGenerator::GetClass(const char *name, Bool_t load, Bool_t silent // loop over and add member functions Bool_t hasConstructor = kFALSE, hasDestructor = kFALSE; - for (int i = 0; i < PyList_GET_SIZE(attrs); ++i) { - PyObject *label = PyList_GET_ITEM(attrs, i); + for (int i = 0; i < PyList_Size(attrs); ++i) { + PyObject *label = PyList_GetItem(attrs, i); Py_IncRef(label); PyObject *attr = PyObject_GetAttr(pyclass, label); // collect only member functions (i.e. callable elements in __dict__) if (PyCallable_Check(attr)) { - std::string mtName = PyUnicode_AsUTF8(label); + const char *mtNameCStr = PyUnicode_AsUTF8AndSize(label, nullptr); + if(!mtNameCStr) { + return nullptr; + } + std::string mtName = mtNameCStr; if (mtName == "__del__") { hasDestructor = kTRUE; @@ -213,7 +255,7 @@ TClass *TPyClassGenerator::GetClass(const char *name, Bool_t load, Bool_t silent PyErr_Clear(); // happens for slots; default to 0 arguments int nVars = - var_names ? PyTuple_GET_SIZE(var_names) - 1 /* self */ : 0 /* TODO: probably large number, all default? */; + var_names ? PyTuple_Size(var_names) - 1 /* self */ : 0 /* TODO: probably large number, all default? */; if (nVars < 0) nVars = 0; Py_DecRef(var_names); diff --git a/bindings/tpython/src/TPyReturn.cxx b/bindings/tpython/src/TPyReturn.cxx index a569a669cbb85..ea62bde3cb98a 100644 --- a/bindings/tpython/src/TPyReturn.cxx +++ b/bindings/tpython/src/TPyReturn.cxx @@ -9,6 +9,8 @@ // * For the list of contributors see $ROOTSYS/README/CREDITS. * // *************************************************************************/ +#include + // Bindings #include "CPyCppyy/API.h" #include "TPyReturn.h" @@ -131,7 +133,7 @@ TPyReturn::operator const char *() const if (fPyObject == Py_None) // for void returns return 0; - const char *s = PyUnicode_AsUTF8(fPyObject); + const char *s = PyUnicode_AsUTF8AndSize(fPyObject, nullptr); if (PyErr_Occurred()) { PyErr_Print(); return 0; @@ -201,16 +203,20 @@ TPyReturn::operator Double_t() const //////////////////////////////////////////////////////////////////////////////// /// Cast python return value to ROOT object with dictionary (may fail; note that -/// you have to use the void* converter, as CINT will not call any other). +/// you have to use the void* converter, as Cling will not call any other). TPyReturn::operator void *() const { PyGILRAII gilRaii; if (fPyObject == Py_None) - return 0; + return nullptr; - return static_cast(CPyCppyy::PyResult{fPyObject}); + if (CPyCppyy::Instance_Check(fPyObject)) { + CPyCppyy::Instance_SetCppOwns(fPyObject); + return CPyCppyy::Instance_AsVoidPtr(fPyObject); + } else + return fPyObject; // borrows reference } //////////////////////////////////////////////////////////////////////////////// diff --git a/bindings/tpython/src/TPython.cxx b/bindings/tpython/src/TPython.cxx index da5da424e7fac..9c858c9e56e79 100644 --- a/bindings/tpython/src/TPython.cxx +++ b/bindings/tpython/src/TPython.cxx @@ -9,6 +9,8 @@ // * For the list of contributors see $ROOTSYS/README/CREDITS. * // *************************************************************************/ +#include + // Bindings // CPyCppyy.h must be go first, since it includes Python.h, which must be // included before any standard header @@ -134,43 +136,8 @@ Bool_t TPython::Initialize() return true; if (!Py_IsInitialized()) { - wchar_t rootStr[] = L"root"; - wchar_t *argv[] = {rootStr}; - int argc = sizeof(argv) / sizeof(argv[0]); -#if PY_VERSION_HEX < 0x030b0000 - Py_Initialize(); -#else - PyStatus status; - PyConfig config; - - PyConfig_InitPythonConfig(&config); - - status = PyConfig_SetArgv(&config, argc, argv); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - std::cerr << "Error when setting command line arguments." << std::endl; - return false; - } - - status = Py_InitializeFromConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - std::cerr << "Error when initializing Python." << std::endl; - return false; - } - PyConfig_Clear(&config); -#endif - - // try again to see if the interpreter is initialized - if (!Py_IsInitialized()) { - // give up ... - std::cerr << "Error: python has not been intialized; returning." << std::endl; - return false; - } - -#if PY_VERSION_HEX < 0x030b0000 - PySys_SetArgv(argc, argv); -#endif + // Trigger the Python initialization indirectly via CPyCppyy + CPyCppyy::Scope_Check(nullptr); mainThreadState = PyEval_SaveThread(); } @@ -180,17 +147,22 @@ Bool_t TPython::Initialize() PyGILRAII gilRaii; // force loading of the ROOT module - const int ret = PyRun_SimpleString("import ROOT"); - if (ret != 0) { - std::cerr << "Error: import ROOT failed, check your PYTHONPATH environmental variable." << std::endl; + PyObject* rootModule = PyImport_ImportModule("ROOT"); + if (!rootModule) { + PyErr_Print(); return false; } + // to trigger the lazy initialization of the C++ runtime - if (PyRun_SimpleString("ROOT.gInterpreter") != 0) { - std::cerr << "Error: initializing ROOT Python module failed." << std::endl; + PyObject* interpreterAttr = PyObject_GetAttrString(rootModule, "gInterpreter"); + if (!interpreterAttr) { + PyErr_Print(); + Py_DecRef(rootModule); return false; } + Py_DecRef(interpreterAttr); + if (!gMainDict) { // retrieve the main dictionary @@ -200,6 +172,15 @@ Bool_t TPython::Initialize() // alive. The gMainDict is only used in Exec(), ExecScript(), and Eval(), // which should not be called after __main__ is garbage collected anyway. } + + // Inject ROOT into __main__ + if (PyDict_SetItemString(gMainDict, "ROOT", rootModule) != 0) { + PyErr_Print(); + Py_DecRef(rootModule); + return false; + } + + Py_DecRef(rootModule); } // python side class construction, managed by ROOT @@ -400,16 +381,7 @@ Bool_t TPython::Exec(const char *cmd, std::any *result, std::string const &resul } // execute the command - PyObjectRef pyObjectResult{ - PyRun_String(command.str().c_str(), Py_file_input, gMainDict, gMainDict)}; - - // test for error - if (pyObjectResult) { - return true; - } - - PyErr_Print(); - return false; + return CPyCppyy::Exec(command.str()); } //////////////////////////////////////////////////////////////////////////////// @@ -452,7 +424,7 @@ void TPython::Prompt() PyGILRAII gilRaii; // enter i/o interactive mode - PyRun_InteractiveLoop(stdin, "\0"); + CPyCppyy::Prompt(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/builtins/cfitsio/CMakeLists.txt b/builtins/cfitsio/CMakeLists.txt index 607c8106a4eb9..f179721885b27 100644 --- a/builtins/cfitsio/CMakeLists.txt +++ b/builtins/cfitsio/CMakeLists.txt @@ -17,14 +17,19 @@ if(WIN32 AND NOT CMAKE_GENERATOR MATCHES Ninja) if(winrtdebug) set(CFITSIO_BUILD_COMMAND_FLAGS "--config Debug") else() - set(CFITSIO_BUILD_COMMAND_FLAGS "--config Release") + set(CFITSIO_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") endif() endif() +# flag required only on Windows, on old alma paltforms it make troubles +if(WIN32) + set(patch_args --ignore-whitespace) +endif() + ExternalProject_Add( BUILTIN_CFITSIO PREFIX ${CFITSIO_PREFIX} - URL https://lcgpackages.web.cern.ch/tarFiles/sources/cfitsio-${CFITSIO_VERSION}.tar.gz + URL ${lcgpackages}/cfitsio-${CFITSIO_VERSION}.tar.gz URL_HASH SHA256=fad44fff274fdda5ffcc0c0fff3bc3c596362722b9292fc8944db91187813600 CMAKE_ARGS -G ${CMAKE_GENERATOR} -DCMAKE_POLICY_VERSION_MINIMUM=3.5 @@ -38,7 +43,7 @@ ExternalProject_Add( -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIRS} -DZLIB_LIBRARIES=$ # Skip the find_package(ZLIB REQUIRED), because we feed CFITSIO our own ZLIB flags. - PATCH_COMMAND git apply --ignore-space-change --ignore-whitespace + PATCH_COMMAND git apply ${patch_args} ${CMAKE_CURRENT_SOURCE_DIR}/cfitsio-no-find-zlib.diff ${CMAKE_CURRENT_SOURCE_DIR}/no-fortran-wrapper.diff BUILD_COMMAND ${CMAKE_COMMAND} --build . ${CFITSIO_BUILD_COMMAND_FLAGS} diff --git a/builtins/freetype/CMakeLists.txt b/builtins/freetype/CMakeLists.txt new file mode 100644 index 0000000000000..92a5ba374782c --- /dev/null +++ b/builtins/freetype/CMakeLists.txt @@ -0,0 +1,83 @@ +# Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. + +# **PLEASE UPDATE ALSO THE FOLLOWING LINE WHEN UPDATING THE VERSION** +# 22 Mar 2026, https://github.com/freetype/freetype/releases/tag/VER-2-14-3 +set(FREETYPE_VERSION 2.14.3) +set(FREETYPE_HASH "e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1") + +set(FREETYPE_PREFIX ${CMAKE_BINARY_DIR}/builtins/FREETYPE-prefix) + +# The CMake of FreeType will call the static library differently if the CMAKE_BUILD_TYPE is Debug, by adding a +# "d" to the name of the file. This is unusual if compared to the behaviour of other ROOT builtins, where the name +# changes only between Linux/macOS and Windows. +if(MSVC) + if(winrtdebug) + set(FREETYPE_POSTFIX d) + endif() + if(NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_FREETYPE_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_FREETYPE_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() + endif() +else() + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(FREETYPE_POSTFIX d) + endif() +endif() +set(FREETYPE_LIBRARY ${FREETYPE_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}freetype${FREETYPE_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) + +ExternalProject_Add( + BUILTIN_FREETYPE + URL ${lcgpackages}/freetype-${FREETYPE_VERSION}.tar.gz + URL_HASH SHA256=${FREETYPE_HASH} + PREFIX ${FREETYPE_PREFIX} + CMAKE_ARGS -G ${CMAKE_GENERATOR} + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=${FREETYPE_PREFIX} + -DCMAKE_INSTALL_LIBDIR=lib + -DFT_DISABLE_BZIP2=TRUE + -DFT_DISABLE_BROTLI=TRUE + -DFT_DISABLE_PNG=TRUE + -DFT_DISABLE_HARFBUZZ=TRUE + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DCMAKE_CXX_VISIBILITY_PRESET=hidden + -DCMAKE_C_VISIBILITY_PRESET=hidden + -DZLIB_LIBRARY=${ZLIB_LIBRARIES} + -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIRS} + BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_FREETYPE_BUILD_COMMAND_FLAGS} + INSTALL_COMMAND ${CMAKE_COMMAND} --install . ${ROOT_FREETYPE_BUILD_COMMAND_FLAGS} + LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 + BUILD_IN_SOURCE 0 + BUILD_BYPRODUCTS ${FREETYPE_LIBRARY} + TIMEOUT 600 +) + +set(incdir ${FREETYPE_PREFIX}/include/freetype2) +file(MAKE_DIRECTORY "${incdir}") + +add_library(Freetype::Freetype IMPORTED STATIC GLOBAL) + +set_target_properties(Freetype::Freetype PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${FREETYPE_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${incdir}") +add_dependencies(Freetype::Freetype BUILTIN_FREETYPE) + +if(builtin_zlib) + add_dependencies(BUILTIN_FREETYPE BUILTIN_ZLIB) +endif() + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(FREETYPE_INCLUDE_DIRS ${incdir} PARENT_SCOPE) +set(FREETYPE_LIBRARIES ${FREETYPE_LIBRARY} PARENT_SCOPE) +set(Freetype_FOUND TRUE PARENT_SCOPE) +set(Freetype_VERSION ${FREETYPE_VERSION} PARENT_SCOPE) diff --git a/builtins/gl2ps/CMakeLists.txt b/builtins/gl2ps/CMakeLists.txt new file mode 100644 index 0000000000000..5ab968966276b --- /dev/null +++ b/builtins/gl2ps/CMakeLists.txt @@ -0,0 +1,69 @@ +# Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. + +# **PLEASE UPDATE ALSO THE FOLLOWING LINE WHEN UPDATING THE VERSION** +# 30 Apr 2020, https://gitlab.onelab.info/gl2ps/gl2ps/-/releases/gl2ps_1_4_2 +set(ROOT_GL2PS_VERSION 1.4.2) +set(ROOT_GL2PS_HASH "8d1c00c1018f96b4b97655482e57dcb0ce42ae2f1d349cd6d4191e7848d9ffe9") +# Backport fix for static Win32 having being overwritten by shared lib: https://gitlab.onelab.info/gl2ps/gl2ps/-/work_items/30 +# We use all seven commits between 1.4.2 and before bump to 1.4.3 +set(ROOT_GL2PS_PATCH_FILE ${CMAKE_CURRENT_SOURCE_DIR}/v142_post_tag_fixes.patch) + +set(ROOT_GL2PS_PREFIX ${CMAKE_BINARY_DIR}/builtins/GL2PS-prefix) + +set(ROOT_GL2PS_LIBRARY ${ROOT_GL2PS_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gl2ps${CMAKE_STATIC_LIBRARY_SUFFIX}) + +if(WIN32 AND NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_GL2PS_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_GL2PS_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() +endif() + +# flag required only on Windows, on old alma paltforms it make troubles +if(WIN32) + set(patch_args --ignore-whitespace) +endif() + +ExternalProject_Add( + BUILTIN_GL2PS + PREFIX ${ROOT_GL2PS_PREFIX} + URL ${lcgpackages}/gl2ps-${ROOT_GL2PS_VERSION}.tgz + URL_HASH SHA256=${ROOT_GL2PS_HASH} + PATCH_COMMAND git apply ${patch_args} ${ROOT_GL2PS_PATCH_FILE} + CMAKE_ARGS -G ${CMAKE_GENERATOR} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX= + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DCMAKE_C_VISIBILITY_PRESET=hidden + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + -DENABLE_PNG=OFF + -DENABLE_ZLIB=OFF + -DBUILD_SHARED_LIBS=OFF + BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_GL2PS_BUILD_COMMAND_FLAGS} + INSTALL_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_GL2PS_BUILD_COMMAND_FLAGS} --target install + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 + LOG_OUTPUT_ON_FAILURE 1 + BUILD_BYPRODUCTS ${ROOT_GL2PS_LIBRARY} + TIMEOUT 600) + +file(MAKE_DIRECTORY ${ROOT_GL2PS_PREFIX}/include) +add_library(gl2ps::gl2ps IMPORTED STATIC GLOBAL) +add_dependencies(gl2ps::gl2ps BUILTIN_GL2PS) +set_target_properties(gl2ps::gl2ps PROPERTIES + IMPORTED_LOCATION ${ROOT_GL2PS_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${ROOT_GL2PS_PREFIX}/include) + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(gl2ps_INCLUDE_DIRS ${ROOT_GL2PS_PREFIX}/include PARENT_SCOPE) +set(gl2ps_LIBRARIES ${ROOT_GL2PS_LIBRARY} PARENT_SCOPE) +set(gl2ps_FOUND TRUE PARENT_SCOPE) +set(gl2ps_VERSION ${ROOT_GL2PS_VERSION} PARENT_SCOPE) diff --git a/builtins/gl2ps/v142_post_tag_fixes.patch b/builtins/gl2ps/v142_post_tag_fixes.patch new file mode 100644 index 0000000000000..a735e3bde0f5b --- /dev/null +++ b/builtins/gl2ps/v142_post_tag_fixes.patch @@ -0,0 +1,708 @@ +From eb23884c2c43f54f6dc2df9d5243c520a5ec7393 Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Fri, 24 Apr 2020 10:37:09 +0200 +Subject: [PATCH 1/7] don't build both static and shared lib; and build shared + lib by default (fixes #30) + +--- + CMakeLists.txt | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 0001c4f..be27ddb 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -49,6 +49,7 @@ project(gl2ps C) + + option(ENABLE_ZLIB "Enable compression using ZLIB" ON) + option(ENABLE_PNG "Enable PNG support" ON) ++option(BUILD_SHARED_LIBS "Enable dynamic/static libs" ON) + + set(GL2PS_MAJOR_VERSION 1) + set(GL2PS_MINOR_VERSION 4) +@@ -139,21 +140,19 @@ if(APPLE) + endif() + + if(OPENGL_FOUND) +- add_library(lib STATIC gl2ps.c gl2ps.h) +- set_target_properties(lib PROPERTIES OUTPUT_NAME gl2ps) ++ add_library(gl2ps gl2ps.c gl2ps.h) + +- add_library(shared SHARED gl2ps.c gl2ps.h) +- target_link_libraries(shared ${EXTERNAL_LIBRARIES}) +- set_target_properties(shared PROPERTIES OUTPUT_NAME gl2ps ++ target_link_libraries(gl2ps ${EXTERNAL_LIBRARIES}) ++ set_target_properties(gl2ps PROPERTIES + VERSION ${GL2PS_MAJOR_VERSION}.${GL2PS_MINOR_VERSION}.${GL2PS_PATCH_VERSION} + SOVERSION ${GL2PS_MAJOR_VERSION}) + if(WIN32 OR CYGWIN) + set_target_properties(shared PROPERTIES + COMPILE_FLAGS "-DGL2PSDLL -DGL2PSDLL_EXPORTS") + endif() +- install(TARGETS lib shared RUNTIME DESTINATION bin +- LIBRARY DESTINATION lib${LIB_SUFFIX} +- ARCHIVE DESTINATION lib${LIB_SUFFIX}) ++ install(TARGETS gl2ps RUNTIME DESTINATION bin ++ LIBRARY DESTINATION lib${LIB_SUFFIX} ++ ARCHIVE DESTINATION lib${LIB_SUFFIX}) + endif() + + if(WIN32) +@@ -171,9 +170,9 @@ install(FILES ${CMAKE_SOURCE_DIR}/gl2psTestSimple.c DESTINATION ${GL2PS_DOC}) + + if(GLUT_FOUND) + add_executable(gl2psTest WIN32 gl2psTest.c) +- target_link_libraries(gl2psTest lib ${EXTERNAL_LIBRARIES}) ++ target_link_libraries(gl2psTest gl2ps ${EXTERNAL_LIBRARIES}) + add_executable(gl2psTestSimple WIN32 gl2psTestSimple.c) +- target_link_libraries(gl2psTestSimple lib ${EXTERNAL_LIBRARIES}) ++ target_link_libraries(gl2psTestSimple gl2ps ${EXTERNAL_LIBRARIES}) + endif() + + find_package(LATEX) +-- +2.34.1 + + +From 056540d1e738bc1a7764fe2bc7b3bf3f58e0e418 Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Fri, 24 Apr 2020 10:38:49 +0200 +Subject: [PATCH 2/7] issue error if opengl is not found (fixes #31) + +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index be27ddb..c178857 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -92,7 +92,7 @@ if(NOT HAVE_VSNPRINTF) + add_definitions(-DHAVE_NO_VSNPRINTF) + endif() + +-find_package(OpenGL) ++find_package(OpenGL REQUIRED) + if(OPENGL_FOUND) + list(APPEND EXTERNAL_INCLUDES ${OPENGL_INCLUDE_DIR}) + list(APPEND EXTERNAL_LIBRARIES ${OPENGL_LIBRARIES}) +-- +2.34.1 + + +From b88558faefc69aa7afe43fdfde572ce4501c57bc Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Fri, 24 Apr 2020 10:47:32 +0200 +Subject: [PATCH 3/7] use CMAKE_HOST_SYSTEM to install doc in correct location + when cross-compiling (fixes #25) + +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index c178857..429aa57 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -155,7 +155,7 @@ if(OPENGL_FOUND) + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + endif() + +-if(WIN32) ++if(CMAKE_HOST_SYSTEM MATCHES Windows) + set(GL2PS_DOC .) + else() + set(GL2PS_DOC share/doc/gl2ps) +-- +2.34.1 + + +From 85b37cf1cc453a40cd45698066f8175542a6992c Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Fri, 24 Apr 2020 10:48:32 +0200 +Subject: [PATCH 4/7] fix windows build (fixes #32) + +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 429aa57..59dc238 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -147,7 +147,7 @@ if(OPENGL_FOUND) + VERSION ${GL2PS_MAJOR_VERSION}.${GL2PS_MINOR_VERSION}.${GL2PS_PATCH_VERSION} + SOVERSION ${GL2PS_MAJOR_VERSION}) + if(WIN32 OR CYGWIN) +- set_target_properties(shared PROPERTIES ++ set_target_properties(gl2ps PROPERTIES + COMPILE_FLAGS "-DGL2PSDLL -DGL2PSDLL_EXPORTS") + endif() + install(TARGETS gl2ps RUNTIME DESTINATION bin +-- +2.34.1 + + +From 896547d24c9826385832a9ff78aaef25310a51fb Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Fri, 24 Apr 2020 11:13:05 +0200 +Subject: [PATCH 5/7] fix the fix - install in default location unless the dir + is set by hand + +--- + CMakeLists.txt | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 59dc238..3569987 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -155,9 +155,7 @@ if(OPENGL_FOUND) + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + endif() + +-if(CMAKE_HOST_SYSTEM MATCHES Windows) +- set(GL2PS_DOC .) +-else() ++if(NOT DEFINED GL2PS_DOC) + set(GL2PS_DOC share/doc/gl2ps) + endif() + +-- +2.34.1 + + +From 13996b51cd4a9c311a5ff6c7acdffa8f9324e606 Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Thu, 30 Apr 2020 08:03:30 +0200 +Subject: [PATCH 6/7] phasing out mailing list + +--- + CMakeLists.txt | 41 +++++++++--------- + gl2ps.c | 42 +++++++++---------- + gl2ps.h | 42 +++++++++---------- + gl2ps.tex | 105 ++++++++++++++++++++++------------------------ + gl2psTest.c | 44 ++++++++++--------- + gl2psTestSimple.c | 44 ++++++++++--------- + 6 files changed, 150 insertions(+), 168 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3569987..58bacdd 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,35 +1,32 @@ + # GL2PS, an OpenGL to PostScript Printing Library + # Copyright (C) 1999-2017 C. Geuzaine + # +-# This program is free software; you can redistribute it and/or +-# modify it under the terms of either: ++# This program is free software; you can redistribute it and/or modify it under ++# the terms of either: + # +-# a) the GNU Library General Public License as published by the Free +-# Software Foundation, either version 2 of the License, or (at your +-# option) any later version; or ++# a) the GNU Library General Public License as published by the Free Software ++# Foundation, either version 2 of the License, or (at your option) any later ++# version; or + # +-# b) the GL2PS License as published by Christophe Geuzaine, either +-# version 2 of the License, or (at your option) any later version. ++# b) the GL2PS License as published by Christophe Geuzaine, either version 2 of ++# the License, or (at your option) any later version. + # +-# This program is distributed in the hope that it will be useful, but +-# WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +-# the GNU Library General Public License or the GL2PS License for +-# more details. ++# This program is distributed in the hope that it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++# FOR A PARTICULAR PURPOSE. See either the GNU Library General Public License ++# or the GL2PS License for more details. + # +-# You should have received a copy of the GNU Library General Public +-# License along with this library in the file named "COPYING.LGPL"; +-# if not, write to the Free Software Foundation, Inc., 675 Mass Ave, +-# Cambridge, MA 02139, USA. ++# You should have received a copy of the GNU Library General Public License ++# along with this library in the file named "COPYING.LGPL"; if not, write to ++# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + # +-# You should have received a copy of the GL2PS License with this +-# library in the file named "COPYING.GL2PS"; if not, I will be glad +-# to provide one. ++# You should have received a copy of the GL2PS License with this library in the ++# file named "COPYING.GL2PS"; if not, I will be glad to provide one. + # +-# For the latest info about gl2ps and a full list of contributors, +-# see http://www.geuz.org/gl2ps/. ++# For the latest info about gl2ps and a full list of contributors, see ++# http://www.geuz.org/gl2ps/. + # +-# Please report all bugs and problems to . ++# Please report all issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. + + cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +diff --git a/gl2ps.c b/gl2ps.c +index c7506ec..06cb633 100644 +--- a/gl2ps.c ++++ b/gl2ps.c +@@ -2,35 +2,33 @@ + * GL2PS, an OpenGL to PostScript Printing Library + * Copyright (C) 1999-2020 C. Geuzaine + * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of either: ++ * This program is free software; you can redistribute it and/or modify it under ++ * the terms of either: + * +- * a) the GNU Library General Public License as published by the Free +- * Software Foundation, either version 2 of the License, or (at your +- * option) any later version; or ++ * a) the GNU Library General Public License as published by the Free Software ++ * Foundation, either version 2 of the License, or (at your option) any later ++ * version; or + * +- * b) the GL2PS License as published by Christophe Geuzaine, either +- * version 2 of the License, or (at your option) any later version. ++ * b) the GL2PS License as published by Christophe Geuzaine, either version 2 of ++ * the License, or (at your option) any later version. + * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +- * the GNU Library General Public License or the GL2PS License for +- * more details. ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ * FOR A PARTICULAR PURPOSE. See either the GNU Library General Public License ++ * or the GL2PS License for more details. + * +- * You should have received a copy of the GNU Library General Public +- * License along with this library in the file named "COPYING.LGPL"; +- * if not, write to the Free Software Foundation, Inc., 51 Franklin +- * Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * You should have received a copy of the GNU Library General Public License ++ * along with this library in the file named "COPYING.LGPL"; if not, write to ++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301, USA. + * +- * You should have received a copy of the GL2PS License with this +- * library in the file named "COPYING.GL2PS"; if not, I will be glad +- * to provide one. ++ * You should have received a copy of the GL2PS License with this library in the ++ * file named "COPYING.GL2PS"; if not, I will be glad to provide one. + * +- * For the latest info about gl2ps and a full list of contributors, +- * see http://www.geuz.org/gl2ps/. ++ * For the latest info about gl2ps and a full list of contributors, see ++ * http://www.geuz.org/gl2ps/. + * +- * Please report all bugs and problems to . ++ * Please report all issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. + */ + + #include "gl2ps.h" +diff --git a/gl2ps.h b/gl2ps.h +index 2fafabb..f8f8c2c 100644 +--- a/gl2ps.h ++++ b/gl2ps.h +@@ -2,35 +2,33 @@ + * GL2PS, an OpenGL to PostScript Printing Library + * Copyright (C) 1999-2020 C. Geuzaine + * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of either: ++ * This program is free software; you can redistribute it and/or modify it under ++ * the terms of either: + * +- * a) the GNU Library General Public License as published by the Free +- * Software Foundation, either version 2 of the License, or (at your +- * option) any later version; or ++ * a) the GNU Library General Public License as published by the Free Software ++ * Foundation, either version 2 of the License, or (at your option) any later ++ * version; or + * +- * b) the GL2PS License as published by Christophe Geuzaine, either +- * version 2 of the License, or (at your option) any later version. ++ * b) the GL2PS License as published by Christophe Geuzaine, either version 2 of ++ * the License, or (at your option) any later version. + * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +- * the GNU Library General Public License or the GL2PS License for +- * more details. ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ * FOR A PARTICULAR PURPOSE. See either the GNU Library General Public License ++ * or the GL2PS License for more details. + * +- * You should have received a copy of the GNU Library General Public +- * License along with this library in the file named "COPYING.LGPL"; +- * if not, write to the Free Software Foundation, Inc., 51 Franklin +- * Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * You should have received a copy of the GNU Library General Public License ++ * along with this library in the file named "COPYING.LGPL"; if not, write to ++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301, USA. + * +- * You should have received a copy of the GL2PS License with this +- * library in the file named "COPYING.GL2PS"; if not, I will be glad +- * to provide one. ++ * You should have received a copy of the GL2PS License with this library in the ++ * file named "COPYING.GL2PS"; if not, I will be glad to provide one. + * +- * For the latest info about gl2ps and a full list of contributors, +- * see http://www.geuz.org/gl2ps/. ++ * For the latest info about gl2ps and a full list of contributors, see ++ * http://www.geuz.org/gl2ps/. + * +- * Please report all bugs and problems to . ++ * Please report all issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. + */ + + #ifndef GL2PS_H +diff --git a/gl2ps.tex b/gl2ps.tex +index 8c3e5be..e8bc318 100644 +--- a/gl2ps.tex ++++ b/gl2ps.tex +@@ -2,35 +2,33 @@ + % GL2PS, an OpenGL to PostScript Printing Library + % Copyright (C) 1999-2020 C. Geuzaine + % +-% This program is free software; you can redistribute it and/or +-% modify it under the terms of either: ++% This program is free software; you can redistribute it and/or modify it under ++% the terms of either: + % +-% a) the GNU Library General Public License as published by the Free +-% Software Foundation, either version 2 of the License, or (at your +-% option) any later version; or ++% a) the GNU Library General Public License as published by the Free Software ++% Foundation, either version 2 of the License, or (at your option) any later ++% version; or + % +-% b) the GL2PS License as published by Christophe Geuzaine, either +-% version 2 of the License, or (at your option) any later version. ++% b) the GL2PS License as published by Christophe Geuzaine, either version 2 of ++% the License, or (at your option) any later version. + % +-% This program is distributed in the hope that it will be useful, but +-% WITHOUT ANY WARRANTY; without even the implied warranty of +-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +-% the GNU Library General Public License or the GL2PS License for +-% more details. ++% This program is distributed in the hope that it will be useful, but WITHOUT ++% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++% FOR A PARTICULAR PURPOSE. See either the GNU Library General Public License ++% or the GL2PS License for more details. + % +-% You should have received a copy of the GNU Library General Public +-% License along with this library in the file named "COPYING.LGPL"; +-% if not, write to the Free Software Foundation, Inc., 51 Franklin +-% Street, Fifth Floor, Boston, MA 02110-1301, USA. ++% You should have received a copy of the GNU Library General Public License ++% along with this library in the file named "COPYING.LGPL"; if not, write to ++% the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ++% MA 02110-1301, USA. + % +-% You should have received a copy of the GL2PS License with this +-% library in the file named "COPYING.GL2PS"; if not, I will be glad +-% to provide one. ++% You should have received a copy of the GL2PS License with this library in the ++% file named "COPYING.GL2PS"; if not, I will be glad to provide one. + % +-% For the latest info about gl2ps and a full list of contributors, +-% see http://www.geuz.org/gl2ps/. ++% For the latest info about gl2ps and a full list of contributors, see ++% http://www.geuz.org/gl2ps/. + % +-% Please report all bugs and problems to . ++% Please report all issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. + + %%tth: \begin{html} GL2PS: an OpenGL to PostScript printing library\end{html} + +@@ -93,18 +91,14 @@ + The latest stable version of GL2PS is gl2ps-1.4.2.tgz. Older + versions and source snapshots are available here. For access to the Git repository use: +-'git clone http://gitlab.onelab.info/gl2ps/gl2ps.git'. ++href="http://geuz.org/gl2ps/src/">here. +

+-For questions and discussions about GL2PS see the gl2ps mailing list. If you +-think you have found a bug you can also file a report directly here. +-You can also subscribe to the gl2ps-announce +-mailing list to be notified automatically when a new version of GL2PS is +-released. ++To access the Git repository use: 'git clone http://gitlab.onelab.info/gl2ps/gl2ps.git'. Please report all ++issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. ++

+
+

+ +@@ -125,29 +119,28 @@ released. + \section{Introduction} + + GL2PS is a C library providing high quality vector output for any OpenGL +-application. The main difference between GL2PS and other similar libraries +-(see section~\ref{sec:links}) is the use of sorting algorithms capable of +-handling intersecting and stretched polygons, as well as non manifold +-objects. GL2PS provides advanced smooth shading and text rendering, culling +-of invisible primitives, mixed vector/bitmap output, and much more... +- +-GL2PS can currently create PostScript (PS), Encapsulated PostScript +-(EPS), Portable Document Format (PDF) and Scalable Vector Graphics (SVG) +-files, as well as \LaTeX\ files for the text fragments. GL2PS also +-provides limited, experimental support for Portable LaTeX Graphics +-(PGF). Adding new vector output formats should be relatively easy; you +-can also use the excellent \href{http://www.pstoedit.net}{pstoedit} +-program to transform the PostScript files generated by GL2PS into many +-other vector formats such as xfig, cgm, wmf, etc. +- +-GL2PS is available at \url{http://www.geuz.org/gl2ps/} and is released under +-the GNU Library General Public License (see +-\href{http://www.geuz.org/gl2ps/COPYING.LGPL}{COPYING.LGPL}). GL2PS can also +-be used under an alternative license that allows (amongst other things, and +-under certain conditions) for static linking with closed-source software +-(see \href{http://www.geuz.org/gl2ps/COPYING.GL2PS}{COPYING.GL2PS}). Any +-corrections, questions or suggestions should be e-mailed to the GL2PS +-mailing list \email{gl2ps@geuz.org}{gl2ps@geuz.org}. ++application. The main difference between GL2PS and other similar libraries (see ++section~\ref{sec:links}) is the use of sorting algorithms capable of handling ++intersecting and stretched polygons, as well as non manifold objects. GL2PS ++provides advanced smooth shading and text rendering, culling of invisible ++primitives, mixed vector/bitmap output, and much more... ++ ++GL2PS can currently create PostScript (PS), Encapsulated PostScript (EPS), ++Portable Document Format (PDF) and Scalable Vector Graphics (SVG) files, as well ++as \LaTeX\ files for the text fragments. GL2PS also provides limited, ++experimental support for Portable LaTeX Graphics (PGF). Adding new vector output ++formats should be relatively easy; you can also use the excellent ++\href{http://www.pstoedit.net}{pstoedit} program to transform the PostScript ++files generated by GL2PS into many other vector formats such as xfig, cgm, wmf, ++etc. ++ ++GL2PS is available at \url{http://www.geuz.org/gl2ps/} and is released under the ++GNU Library General Public License (see ++\href{http://www.geuz.org/gl2ps/COPYING.LGPL}{COPYING.LGPL}). GL2PS can also be ++used under an alternative license that allows (amongst other things, and under ++certain conditions) for static linking with closed-source software (see ++\href{http://www.geuz.org/gl2ps/COPYING.GL2PS}{COPYING.GL2PS}). Issues can be ++reported through \url{https://gitlab.onelab.info/gl2ps/gl2ps/issues}. + + \section{Usage} + +diff --git a/gl2psTest.c b/gl2psTest.c +index 15b4776..744917e 100644 +--- a/gl2psTest.c ++++ b/gl2psTest.c +@@ -1,36 +1,34 @@ + /* + * GL2PS, an OpenGL to PostScript Printing Library +- * Copyright (C) 1999-2017 Christophe Geuzaine ++ * Copyright (C) 1999-2020 C. Geuzaine + * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of either: ++ * This program is free software; you can redistribute it and/or modify it under ++ * the terms of either: + * +- * a) the GNU Library General Public License as published by the Free +- * Software Foundation, either version 2 of the License, or (at your +- * option) any later version; or ++ * a) the GNU Library General Public License as published by the Free Software ++ * Foundation, either version 2 of the License, or (at your option) any later ++ * version; or + * +- * b) the GL2PS License as published by Christophe Geuzaine, either +- * version 2 of the License, or (at your option) any later version. ++ * b) the GL2PS License as published by Christophe Geuzaine, either version 2 of ++ * the License, or (at your option) any later version. + * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +- * the GNU Library General Public License or the GL2PS License for +- * more details. ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ * FOR A PARTICULAR PURPOSE. See either the GNU Library General Public License ++ * or the GL2PS License for more details. + * +- * You should have received a copy of the GNU Library General Public +- * License along with this library in the file named "COPYING.LGPL"; +- * if not, write to the Free Software Foundation, Inc., 51 Franklin +- * Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * You should have received a copy of the GNU Library General Public License ++ * along with this library in the file named "COPYING.LGPL"; if not, write to ++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301, USA. + * +- * You should have received a copy of the GL2PS License with this +- * library in the file named "COPYING.GL2PS"; if not, I will be glad +- * to provide one. ++ * You should have received a copy of the GL2PS License with this library in the ++ * file named "COPYING.GL2PS"; if not, I will be glad to provide one. + * +- * For the latest info about gl2ps and a full list of contributors, +- * see http://www.geuz.org/gl2ps/. ++ * For the latest info about gl2ps and a full list of contributors, see ++ * http://www.geuz.org/gl2ps/. + * +- * Please report all bugs and problems to . ++ * Please report all issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. + */ + + /* +diff --git a/gl2psTestSimple.c b/gl2psTestSimple.c +index 366db54..3e40b6d 100644 +--- a/gl2psTestSimple.c ++++ b/gl2psTestSimple.c +@@ -1,36 +1,34 @@ + /* + * GL2PS, an OpenGL to PostScript Printing Library +- * Copyright (C) 1999-2017 Christophe Geuzaine ++ * Copyright (C) 1999-2020 C. Geuzaine + * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of either: ++ * This program is free software; you can redistribute it and/or modify it under ++ * the terms of either: + * +- * a) the GNU Library General Public License as published by the Free +- * Software Foundation, either version 2 of the License, or (at your +- * option) any later version; or ++ * a) the GNU Library General Public License as published by the Free Software ++ * Foundation, either version 2 of the License, or (at your option) any later ++ * version; or + * +- * b) the GL2PS License as published by Christophe Geuzaine, either +- * version 2 of the License, or (at your option) any later version. ++ * b) the GL2PS License as published by Christophe Geuzaine, either version 2 of ++ * the License, or (at your option) any later version. + * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +- * the GNU Library General Public License or the GL2PS License for +- * more details. ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ * FOR A PARTICULAR PURPOSE. See either the GNU Library General Public License ++ * or the GL2PS License for more details. + * +- * You should have received a copy of the GNU Library General Public +- * License along with this library in the file named "COPYING.LGPL"; +- * if not, write to the Free Software Foundation, Inc., 51 Franklin +- * Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * You should have received a copy of the GNU Library General Public License ++ * along with this library in the file named "COPYING.LGPL"; if not, write to ++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ++ * MA 02110-1301, USA. + * +- * You should have received a copy of the GL2PS License with this +- * library in the file named "COPYING.GL2PS"; if not, I will be glad +- * to provide one. ++ * You should have received a copy of the GL2PS License with this library in the ++ * file named "COPYING.GL2PS"; if not, I will be glad to provide one. + * +- * For the latest info about gl2ps and a full list of contributors, +- * see http://www.geuz.org/gl2ps/. ++ * For the latest info about gl2ps and a full list of contributors, see ++ * http://www.geuz.org/gl2ps/. + * +- * Please report all bugs and problems to . ++ * Please report all issues on https://gitlab.onelab.info/gl2ps/gl2ps/issues. + */ + + /* +-- +2.34.1 + + +From 092901a4f53b003f66d5a7a3b100c3a933005130 Mon Sep 17 00:00:00 2001 +From: Christophe Geuzaine +Date: Sun, 12 Jul 2020 10:04:45 +0200 +Subject: [PATCH 7/7] clamp float RGBA values in [0,1] to fix #21 #34 + +--- + gl2ps.c | 30 ++++++++++++++++++++++++++---- + 1 file changed, 26 insertions(+), 4 deletions(-) + +diff --git a/gl2ps.c b/gl2ps.c +index 06cb633..e4893fc 100644 +--- a/gl2ps.c ++++ b/gl2ps.c +@@ -4456,17 +4456,33 @@ static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex, + int offs = 0; + unsigned long imap; + double dmax = ~1UL; ++ GLfloat tmp; + + /* FIXME: temp bux fix for 64 bit archs: */ + if(sizeof(unsigned long) == 8) dmax = dmax - 2048.; + +- imap = (unsigned long)((vertex->rgba[0]) * dmax); ++ tmp = vertex->rgba[0]; ++ if(tmp > 1) ++ tmp = 1.0F; ++ else if(tmp < 0) ++ tmp = 0.0F; ++ imap = (unsigned long)(tmp * dmax); + offs += (*action)(imap, 1); + +- imap = (unsigned long)((vertex->rgba[1]) * dmax); ++ tmp = vertex->rgba[1]; ++ if(tmp > 1) ++ tmp = 1.0F; ++ else if(tmp < 0) ++ tmp = 0.0F; ++ imap = (unsigned long)(tmp * dmax); + offs += (*action)(imap, 1); + +- imap = (unsigned long)((vertex->rgba[2]) * dmax); ++ tmp = vertex->rgba[2]; ++ if(tmp > 1) ++ tmp = 1.0F; ++ else if(tmp < 0) ++ tmp = 0.0F; ++ imap = (unsigned long)(tmp * dmax); + offs += (*action)(imap, 1); + + return offs; +@@ -4481,6 +4497,7 @@ static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, + int offs = 0; + unsigned long imap; + double dmax = ~1UL; ++ GLfloat tmp; + + /* FIXME: temp bux fix for 64 bit archs: */ + if(sizeof(unsigned long) == 8) dmax = dmax - 2048.; +@@ -4490,7 +4507,12 @@ static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, + + sigbyte /= 8; + +- imap = (unsigned long)((vertex->rgba[3]) * dmax); ++ tmp = vertex->rgba[3]; ++ if(tmp > 1) ++ tmp = 1.0F; ++ else if(tmp < 0) ++ tmp = 0.0F; ++ imap = (unsigned long)(tmp * dmax); + + offs += (*action)(imap, sigbyte); + +-- +2.34.1 + diff --git a/builtins/libgif/CMakeLists.txt b/builtins/libgif/CMakeLists.txt index eed00c1cf53bf..48a2ed37254b3 100644 --- a/builtins/libgif/CMakeLists.txt +++ b/builtins/libgif/CMakeLists.txt @@ -19,22 +19,28 @@ if(WIN32 AND NOT CMAKE_GENERATOR MATCHES Ninja) if(winrtdebug) set(ROOT_LIBGIF_BUILD_COMMAND_FLAGS "--config Debug") else() - set(ROOT_LIBGIF_BUILD_COMMAND_FLAGS "--config Release") + set(ROOT_LIBGIF_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") endif() endif() +# flag required only on Windows, on old alma paltforms it make troubles +if(WIN32) + set(patch_args --ignore-whitespace) +endif() + ExternalProject_Add( BUILTIN_LIBGIF PREFIX ${ROOT_LIBGIF_PREFIX} - URL https://lcgpackages.web.cern.ch/tarFiles/sources/giflib-${ROOT_LIBGIF_VERSION}.tar.gz + URL ${lcgpackages}/giflib-${ROOT_LIBGIF_VERSION}.tar.gz URL_HASH SHA256=${ROOT_LIBGIF_HASH} - PATCH_COMMAND git apply ${ROOT_LIBGIF_PATCH_FILE} + PATCH_COMMAND git apply ${patch_args} ${ROOT_LIBGIF_PATCH_FILE} CMAKE_ARGS -G ${CMAKE_GENERATOR} -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX= -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden + -DCMAKE_C_VISIBILITY_PRESET=hidden BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_LIBGIF_BUILD_COMMAND_FLAGS} INSTALL_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_LIBGIF_BUILD_COMMAND_FLAGS} --target install LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 @@ -48,3 +54,11 @@ set_target_properties(GIF::GIF PROPERTIES IMPORTED_LOCATION ${ROOT_LIBGIF_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES ${ROOT_LIBGIF_PREFIX}/include ) +add_dependencies(GIF::GIF BUILTIN_LIBGIF) + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(GIF_INCLUDE_DIRS ${ROOT_LIBGIF_PREFIX}/include PARENT_SCOPE) +set(GIF_LIBRARIES ${ROOT_LIBGIF_LIBRARY} PARENT_SCOPE) +set(GIF_FOUND TRUE PARENT_SCOPE) +set(GIF_VERSION ${ROOT_LIBGIF_VERSION} PARENT_SCOPE) diff --git a/builtins/libjpeg/CMakeLists.txt b/builtins/libjpeg/CMakeLists.txt index 472c72cea3b7e..45be561d35c32 100644 --- a/builtins/libjpeg/CMakeLists.txt +++ b/builtins/libjpeg/CMakeLists.txt @@ -22,7 +22,7 @@ if(WIN32 AND NOT CMAKE_GENERATOR MATCHES Ninja) if(winrtdebug) set(ROOT_LIBJPEG_BUILD_COMMAND_FLAGS "--config Debug") else() - set(ROOT_LIBJPEG_BUILD_COMMAND_FLAGS "--config Release") + set(ROOT_LIBJPEG_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") endif() endif() @@ -38,6 +38,7 @@ ExternalProject_Add( -DCMAKE_INSTALL_LIBDIR=/lib -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden + -DCMAKE_C_VISIBILITY_PRESET=hidden -DENABLE_SHARED=OFF -DWITH_TURBOJPEG=OFF -DWITH_SIMD=OFF @@ -56,3 +57,11 @@ set_target_properties(JPEG::JPEG PROPERTIES IMPORTED_LOCATION ${ROOT_LIBJPEG_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES ${ROOT_LIBJPEG_PREFIX}/include ) +add_dependencies(JPEG::JPEG BUILTIN_LIBJPEG) + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(JPEG_INCLUDE_DIRS ${${ROOT_LIBJPEG_PREFIX}/include} PARENT_SCOPE) +set(JPEG_LIBRARIES ${ROOT_LIBJPEG_LIBRARY} PARENT_SCOPE) +set(JPEG_FOUND TRUE PARENT_SCOPE) +set(JPEG_VERSION ${ROOT_LIBJPEG_VERSION} PARENT_SCOPE) diff --git a/builtins/libpng/CMakeLists.txt b/builtins/libpng/CMakeLists.txt index 942a40f039356..c62eae3226631 100644 --- a/builtins/libpng/CMakeLists.txt +++ b/builtins/libpng/CMakeLists.txt @@ -13,17 +13,32 @@ set(ROOT_LIBPNG_PREFIX ${CMAKE_BINARY_DIR}/builtins/LIBPNG-prefix) # Here we need two cases because the library has two different names on Linux/macOS and Windows if(MSVC) - set(ROOT_LIBPNG_LIBRARY ${ROOT_LIBPNG_PREFIX}/lib/libpng16_static${CMAKE_STATIC_LIBRARY_SUFFIX}) + if(winrtdebug) + set(LIBPNG_POSTFIX d) + endif() + if(NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_LIBPNG_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_LIBPNG_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() + endif() + set(ROOT_LIBPNG_LIBRARY ${ROOT_LIBPNG_PREFIX}/lib/libpng16_static${LIBPNG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) else() set(ROOT_LIBPNG_LIBRARY ${ROOT_LIBPNG_PREFIX}/lib/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}) endif() -if(WIN32 AND NOT CMAKE_GENERATOR MATCHES Ninja) - if(winrtdebug) - set(ROOT_LIBPNG_BUILD_COMMAND_FLAGS "--config Debug") - else() - set(ROOT_LIBPNG_BUILD_COMMAND_FLAGS "--config Release") - endif() +# If zlib is not builtin, the string will be empty, nothing special to be +# done: we rely on libpng CMake to find zlib. +# If zlib is builtin, we need to direct the builtin libpng to it. +# For that, the libpng recommended way (see their CMakeLists) +# is to use the CMake ZLIB_ROOT variable, which has nothing to do with ROOT +# despite the name: it's a standard CMake convention to direct the search of +# the find macro. +# Therefore we set it to the prefix path of the builtin zlib in ROOT's +# build directory. +if(builtin_zlib) + set(ZLIB_ROOT_OPTION "-DZLIB_ROOT=${ROOT_ZLIB_PREFIX}") endif() ExternalProject_Add( @@ -38,10 +53,12 @@ ExternalProject_Add( -DCMAKE_INSTALL_LIBDIR=/lib -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden + -DCMAKE_C_VISIBILITY_PRESET=hidden -DPNG_SHARED=OFF -DPNG_STATIC=ON + -DZLIB_LIBRARY=${ZLIB_LIBRARIES} -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIRS} - -DZLIB_LIBRARY=$ + ${ZLIB_ROOT_OPTION} BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_LIBPNG_BUILD_COMMAND_FLAGS} INSTALL_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_LIBPNG_BUILD_COMMAND_FLAGS} --target install LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 @@ -55,3 +72,15 @@ set_target_properties(PNG::PNG PROPERTIES IMPORTED_LOCATION ${ROOT_LIBPNG_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES ${ROOT_LIBPNG_PREFIX}/include ) +add_dependencies(PNG::PNG BUILTIN_LIBPNG) + +if(builtin_zlib) + add_dependencies(BUILTIN_LIBPNG BUILTIN_ZLIB) +endif() + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(PNG_INCLUDE_DIRS ${ROOT_LIBPNG_PREFIX}/include PARENT_SCOPE) +set(PNG_LIBRARIES ${ROOT_LIBPNG_LIBRARY} PARENT_SCOPE) +set(PNG_FOUND TRUE PARENT_SCOPE) +set(PNG_VERSION ${ROOT_LIBPNG_VERSION} PARENT_SCOPE) diff --git a/builtins/lz4/CMakeLists.txt b/builtins/lz4/CMakeLists.txt index d7747968ccade..77901d23b0a4e 100644 --- a/builtins/lz4/CMakeLists.txt +++ b/builtins/lz4/CMakeLists.txt @@ -11,10 +11,7 @@ set(ROOT_LZ4_HASH "537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f project(LZ4 C) -set(LZ4_VERSION ${ROOT_LZ4_VERSION} CACHE INTERNAL "" FORCE) # used in roottest - set(ROOT_LZ4_PREFIX ${CMAKE_BINARY_DIR}/builtins/LZ4-prefix) - set(ROOT_LZ4_LIBRARY ${ROOT_LZ4_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}lz4${CMAKE_STATIC_LIBRARY_SUFFIX}) if(MSVC) @@ -24,15 +21,23 @@ if(MSVC) -DCMAKE_CXXFLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_CXXFLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_CXXFLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG}) + if(NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_LZ4_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_LZ4_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() + endif() endif() ExternalProject_Add( BUILTIN_LZ4 - URL https://lcgpackages.web.cern.ch/tarFiles/sources/lz4-${ROOT_LZ4_VERSION}.tar.gz + URL ${lcgpackages}/lz4-${ROOT_LZ4_VERSION}.tar.gz URL_HASH SHA256=${ROOT_LZ4_HASH} PREFIX ${ROOT_LZ4_PREFIX} SOURCE_SUBDIR "build/cmake" CMAKE_ARGS -G ${CMAKE_GENERATOR} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX= -DCMAKE_INSTALL_LIBDIR=/lib -DCMAKE_POSITION_INDEPENDENT_CODE=ON @@ -41,8 +46,8 @@ ExternalProject_Add( -DBUILD_SHARED_LIBS=OFF -DBUILD_STATIC_LIBS=ON ${lz4_extra_cmake_args} - BUILD_COMMAND ${CMAKE_COMMAND} --build "/" --config $ - INSTALL_COMMAND ${CMAKE_COMMAND} --install "/" --config $ + BUILD_COMMAND ${CMAKE_COMMAND} --build "/" ${ROOT_LZ4_BUILD_COMMAND_FLAGS} + INSTALL_COMMAND ${CMAKE_COMMAND} --install "/" ${ROOT_LZ4_BUILD_COMMAND_FLAGS} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 BUILD_IN_SOURCE 1 BUILD_BYPRODUCTS ${ROOT_LZ4_LIBRARY} @@ -50,10 +55,17 @@ ExternalProject_Add( ) -set(LIBLZ4_INCLUDE_DIR ${ROOT_LZ4_PREFIX}/include) -file(MAKE_DIRECTORY ${LIBLZ4_INCLUDE_DIR}) +set(LZ4_INCLUDE_DIR ${ROOT_LZ4_PREFIX}/include) +file(MAKE_DIRECTORY ${LZ4_INCLUDE_DIR}) + +add_library(LZ4::LZ4 STATIC IMPORTED GLOBAL) +add_dependencies(LZ4::LZ4 BUILTIN_LZ4) +target_include_directories(LZ4::LZ4 INTERFACE ${LZ4_INCLUDE_DIR}) +set_target_properties(LZ4::LZ4 PROPERTIES IMPORTED_LOCATION ${ROOT_LZ4_LIBRARY}) -add_library(LibLZ4 STATIC IMPORTED GLOBAL) -add_library(LZ4::LZ4 ALIAS LibLZ4) -target_include_directories(LibLZ4 INTERFACE ${LIBLZ4_INCLUDE_DIR}) -set_target_properties(LibLZ4 PROPERTIES IMPORTED_LOCATION ${ROOT_LZ4_LIBRARY}) +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR} PARENT_SCOPE) +set(LZ4_LIBRARIES ${ROOT_LZ4_LIBRARY} PARENT_SCOPE) +set(LZ4_FOUND TRUE PARENT_SCOPE) +set(LZ4_VERSION ${ROOT_LZ4_VERSION} PARENT_SCOPE) diff --git a/builtins/lzma/CMakeLists.txt b/builtins/lzma/CMakeLists.txt index dbefca08d2e2b..0c10ec273c6a3 100644 --- a/builtins/lzma/CMakeLists.txt +++ b/builtins/lzma/CMakeLists.txt @@ -21,6 +21,13 @@ if(MSVC) -DCMAKE_CXXFLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_CXXFLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_CXXFLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG}) + if(NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_LZMA_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_LZMA_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() + endif() else() if(CMAKE_OSX_SYSROOT) set(liblzma_flags "-isysroot\ ${CMAKE_OSX_SYSROOT}") @@ -37,10 +44,12 @@ ExternalProject_Add( URL_HASH SHA256=${ROOT_LZMA_HASH} PREFIX ${ROOT_LZMA_PREFIX} CMAKE_ARGS -G ${CMAKE_GENERATOR} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX= -DCMAKE_INSTALL_LIBDIR=/lib -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden + -DCMAKE_C_VISIBILITY_PRESET=hidden -DBUILD_SHARED_LIBS=OFF -DENABLE_SCRIPTS=OFF -DXZ_TOOL=OFF @@ -48,8 +57,8 @@ ExternalProject_Add( -DLZMADEC=OFF -DLZMAINFO=OFF ${lzma_extra_cmake_args} - BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $ --target liblzma - INSTALL_COMMAND ${CMAKE_COMMAND} --install . --config $ --component liblzma_Development + BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_LZMA_BUILD_COMMAND_FLAGS} --target liblzma + INSTALL_COMMAND ${CMAKE_COMMAND} --install . ${ROOT_LZMA_BUILD_COMMAND_FLAGS} --component liblzma_Development LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 BUILD_IN_SOURCE 1 BUILD_BYPRODUCTS ${LIBLZMA_LIBRARIES} @@ -64,3 +73,10 @@ add_library(LibLZMA STATIC IMPORTED GLOBAL) add_library(LibLZMA::LibLZMA ALIAS LibLZMA) target_include_directories(LibLZMA INTERFACE ${LIBLZMA_INCLUDE_DIR}) set_target_properties(LibLZMA PROPERTIES IMPORTED_LOCATION ${LIBLZMA_LIBRARIES}) + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(LIBLZMA_INCLUDE_DIRS ${LibLZMA_INCLUDE_DIR} PARENT_SCOPE) +set(LIBLZMA_LIBRARIES ${LIBLZMA_LIBRARIES} PARENT_SCOPE) +set(LibLZMA_FOUND TRUE PARENT_SCOPE) +set(LibLZMA_VERSION ${ROOT_LZMA_VERSION} PARENT_SCOPE) diff --git a/builtins/openssl/CMakeLists.txt b/builtins/openssl/CMakeLists.txt index 043745825a620..e3ff238beee22 100644 --- a/builtins/openssl/CMakeLists.txt +++ b/builtins/openssl/CMakeLists.txt @@ -14,7 +14,7 @@ foreach(suffix FOUND INCLUDE_DIR INCLUDE_DIRS CRYPTO_LIBRARY SSL_LIBRARY LIBRARY endforeach() set(OPENSSL_VERSION "3.5.0") -set(OPENSSL_URL "http://lcgpackages.web.cern.ch/lcgpackages/tarFiles/sources/openssl-${OPENSSL_VERSION}.tar.gz") +set(OPENSSL_URL "${lcgpackages}/openssl-${OPENSSL_VERSION}.tar.gz") set(OPENSSL_URLHASH "SHA256=344d0a79f1a9b08029b0744e2cc401a43f9c90acd1044d09a530b4885a8e9fc0") set(OPENSSL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/OPENSSL-prefix) diff --git a/builtins/rendercore/RenderCore-1.8.tar.gz b/builtins/rendercore/RenderCore-1.8.tar.gz deleted file mode 100644 index 084656c909f4e..0000000000000 Binary files a/builtins/rendercore/RenderCore-1.8.tar.gz and /dev/null differ diff --git a/builtins/rendercore/RenderCore-1.9.tar.gz b/builtins/rendercore/RenderCore-1.9.tar.gz new file mode 100644 index 0000000000000..e90160f6570fe Binary files /dev/null and b/builtins/rendercore/RenderCore-1.9.tar.gz differ diff --git a/builtins/xrootd/CMakeLists.txt b/builtins/xrootd/CMakeLists.txt index 00abd0d93cb77..b87fe68eb5207 100644 --- a/builtins/xrootd/CMakeLists.txt +++ b/builtins/xrootd/CMakeLists.txt @@ -6,7 +6,7 @@ include(ExternalProject) -set(XROOTD_VERSION "5.9.1") +set(XROOTD_VERSION "5.9.2") set(XROOTD_PREFIX ${CMAKE_BINARY_DIR}/XROOTD-prefix) message(STATUS "Downloading and building XROOTD version ${XROOTD_VERSION}") @@ -26,8 +26,8 @@ endif() ExternalProject_Add( BUILTIN_XROOTD - URL http://lcgpackages.web.cern.ch/lcgpackages/tarFiles/sources/xrootd-${XROOTD_VERSION}.tar.gz - URL_HASH SHA256=39946509a50e790ab3fcc77ba0f4c9b66abef221262756aa8bb2494f00a0e321 + URL ${lcgpackages}/xrootd-${XROOTD_VERSION}.tar.gz + URL_HASH SHA256=e29edb755d5f728eff0c74f7bd8cec35c954239ea747975eebd9c1e2bd61edb5 INSTALL_DIR ${XROOTD_PREFIX} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH:STRING=${OPENSSL_PREFIX} diff --git a/builtins/zeromq/cppzmq/CMakeLists.txt b/builtins/zeromq/cppzmq/CMakeLists.txt index c8e539fd94d55..4aa1240ce3edd 100644 --- a/builtins/zeromq/cppzmq/CMakeLists.txt +++ b/builtins/zeromq/cppzmq/CMakeLists.txt @@ -2,7 +2,6 @@ include(ExternalProject) set(cppzmq_HEADER_PATH ${CMAKE_CURRENT_BINARY_DIR}/BUILTIN_cppzmq-prefix/src/BUILTIN_cppzmq) -set(lcgpackages http://lcgpackages.web.cern.ch/lcgpackages/tarFiles/sources) set(cppzmq_version 4.10.0) ExternalProject_Add(BUILTIN_cppzmq URL ${lcgpackages}/cppzmq-${cppzmq_version}.tar.gz diff --git a/builtins/zeromq/libzmq/CMakeLists.txt b/builtins/zeromq/libzmq/CMakeLists.txt index 2991a8d0e21bf..6e933c5d494ec 100644 --- a/builtins/zeromq/libzmq/CMakeLists.txt +++ b/builtins/zeromq/libzmq/CMakeLists.txt @@ -13,7 +13,6 @@ else() set(cxx_visibility_flag "") endif() -set(lcgpackages http://lcgpackages.web.cern.ch/lcgpackages/tarFiles/sources) set(libzeromq_version 4.3.5) ExternalProject_Add(BUILTIN_ZeroMQ URL ${lcgpackages}/zeromq-${libzeromq_version}.tar.gz diff --git a/builtins/zlib/CMakeLists.txt b/builtins/zlib/CMakeLists.txt index aa5755adb5cf3..85e69387c88af 100644 --- a/builtins/zlib/CMakeLists.txt +++ b/builtins/zlib/CMakeLists.txt @@ -1,140 +1,76 @@ -# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. +# Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. # All rights reserved. # # For the licensing terms see $ROOTSYS/LICENSE. # For the list of contributors see $ROOTSYS/README/CREDITS. -project(ZLIB C) - -set(ZLIB_PUBLIC_HEADERS - zconf.h - zlib.h -) - -set(ZLIB_PRIVATE_HEADERS - crc32.h - deflate.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) - -set(ZLIBCF_PRIVATE_HEADERS - crc32.h - deflate_cf.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) - -set(ZLIB_SOURCES - adler32.c - compress.c - crc32.c - deflate.c - gzclose.c - gzlib.c - gzread.c - gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees.c - uncompr.c - zutil.c -) - -set(ZLIBCF_SOURCES - adler32_cf.c - compress.c - crc32_cf.c - deflate_cf.c - gzclose.c - gzlib.c - gzread.c - gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees_cf.c - uncompr.c - zutil.c -) - -unset(ZLIB_FOUND CACHE) -unset(ZLIB_FOUND PARENT_SCOPE) -set(ZLIB_FOUND TRUE CACHE BOOL "" FORCE) - -file(STRINGS zlib.h ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$") -string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}") -string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}") -string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}") -set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}") - -set(ZLIB_VERSION_TWEAK "") -if("${ZLIB_H}" MATCHES "ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+)") - set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}") - string(APPEND ZLIB_VERSION_STRING ".${ZLIB_VERSION_TWEAK}") -endif() - -set(ZLIB_VERSION ${ZLIB_VERSION_STRING} CACHE INTERNAL "") -set(ZLIB_VERSION_STRING ${ZLIB_VERSION_STRING} CACHE INTERNAL "") - -set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "") -set(ZLIB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "") - -if((CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64|X86_64|aarch64") AND (CMAKE_SYSTEM_NAME MATCHES "Linux")) - # Calling helper to avoid using old unsupported binutils (e.g. with SL6) - # macro is returning extra ${ROOT_DEFINITIONS} used after in ZLIB-CF - root_check_assembler() - # Calling helper to avoid using old unsupported binutils (e.g. with Centos7 - # and native gcc compiler 4.8.5) - # Macros are returning bools SSE_SUPPORT & AVX2_SUPPORT - root_check_sse41() - root_check_avx2() - if(SSE_SUPPORT OR AVX2_SUPPORT) - set(ZLIB_CF TRUE CACHE INTERNAL "") - endif() -endif() - -if(ZLIB_CF) - add_library(ZLIB STATIC ${ZLIB_PUBLIC_HEADERS} ${ZLIBCF_PRIVATE_HEADERS} ${ZLIBCF_SOURCES}) +# **PLEASE UPDATE ALSO THE FOLLOWING LINE WHEN UPDATING THE VERSION** +# 17 Feb 2026, https://github.com/madler/zlib/releases/tag/v1.3.2 +set(ROOT_ZLIB_VERSION 1.3.2) +set(ROOT_ZLIB_HASH "bb329a0a2cd0274d05519d61c667c062e06990d72e125ee2dfa8de64f0119d16") + +set(ROOT_ZLIB_PREFIX ${CMAKE_BINARY_DIR}/builtins/ZLIB-prefix PARENT_SCOPE) +set(ROOT_ZLIB_PREFIX ${CMAKE_BINARY_DIR}/builtins/ZLIB-prefix) + +# Here we need two cases because the library has two different names on Linux/macOS and Windows +if(MSVC) + if(winrtdebug) + set(ZLIB_POSTFIX d) + endif() + if(NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_ZLIB_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_ZLIB_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() + endif() + set(ROOT_ZLIB_LIBRARY ${ROOT_ZLIB_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}zs${ZLIB_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) + # In the MSVC case, we forward the default C++ configuration flags because + # they are changed by ROOT in SetUpWindows.cmake. + set(zlib_extra_cmake_args + -DCMAKE_CXXFLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} + -DCMAKE_CXXFLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} + -DCMAKE_CXXFLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG}) else() - add_library(ZLIB STATIC ${ZLIB_PUBLIC_HEADERS} ${ZLIB_PRIVATE_HEADERS} ${ZLIB_SOURCES}) + set(ROOT_ZLIB_LIBRARY ${ROOT_ZLIB_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}z${CMAKE_STATIC_LIBRARY_SUFFIX}) endif() -set_target_properties(ZLIB PROPERTIES C_VISIBILITY_PRESET hidden POSITION_INDEPENDENT_CODE ON) -target_include_directories(ZLIB INTERFACE $) +ExternalProject_Add( + BUILTIN_ZLIB + URL ${lcgpackages}/zlib-${ROOT_ZLIB_VERSION}.tar.gz + URL_HASH SHA256=${ROOT_ZLIB_HASH} + PREFIX ${ROOT_ZLIB_PREFIX} + CMAKE_ARGS -G ${CMAKE_GENERATOR} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX= + -DCMAKE_INSTALL_LIBDIR=/lib + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DCMAKE_CXX_VISIBILITY_PRESET=hidden + -DCMAKE_C_VISIBILITY_PRESET=hidden + -DZLIB_BUILD_TESTING=OFF + -DZLIB_BUILD_SHARED=OFF + ${zlib_extra_cmake_args} + BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ROOT_ZLIB_BUILD_COMMAND_FLAGS} + INSTALL_COMMAND ${CMAKE_COMMAND} --install . ${ROOT_ZLIB_BUILD_COMMAND_FLAGS} + LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 LOG_TEST 1 + BUILD_BYPRODUCTS ${ROOT_ZLIB_LIBRARY} + TIMEOUT 600 +) -if((CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64|X86_64") AND (CMAKE_SYSTEM_NAME MATCHES "Linux")) - target_compile_options(ZLIB PRIVATE -Wno-unused-function -O3 -mpclmul -Wno-attribute-alias ${ROOT_DEFINITIONS}) -else() - if(NOT MSVC) - target_compile_options(ZLIB PRIVATE -O3) - endif() -endif() +set(ZLIB_INCLUDE_DIR ${ROOT_ZLIB_PREFIX}/include) +file(MAKE_DIRECTORY ${ZLIB_INCLUDE_DIR}) +set_property(GLOBAL APPEND PROPERTY ROOT_BUILTIN_TARGETS ZLIB::ZLIB) +add_library(ZLIB STATIC IMPORTED GLOBAL) add_library(ZLIB::ZLIB ALIAS ZLIB) +target_include_directories(ZLIB INTERFACE ${ZLIB_INCLUDE_DIR}) +set_target_properties(ZLIB PROPERTIES IMPORTED_LOCATION ${ROOT_ZLIB_LIBRARY}) -set(ZLIB_LIBRARY $ CACHE INTERNAL FORCE "") -set(ZLIB_LIBRARIES ZLIB::ZLIB CACHE INTERNAL "") - -if(DEFINED ZLIB_LIBRARY_DEBUG) - set(ZLIB_LIBRARY_DEBUG ${ZLIB_LIBRARY} CACHE INTERNAL "") -endif() +add_dependencies(ZLIB BUILTIN_ZLIB) -if(DEFINED ZLIB_LIBRARY_RELEASE) - set(ZLIB_LIBRARY_RELEASE ${ZLIB_LIBRARY} CACHE INTERNAL "") -endif() - -set_property(GLOBAL APPEND PROPERTY ROOT_BUILTIN_TARGETS ZLIB::ZLIB) +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR} PARENT_SCOPE) +set(ZLIB_LIBRARIES ${ROOT_ZLIB_LIBRARY} PARENT_SCOPE) +set(ZLIB_FOUND TRUE PARENT_SCOPE) +set(ZLIB_VERSION ${ROOT_ZLIB_VERSION} PARENT_SCOPE) diff --git a/builtins/zlib/adler32.c b/builtins/zlib/adler32.c deleted file mode 100644 index eeadf98d089c9..0000000000000 --- a/builtins/zlib/adler32.c +++ /dev/null @@ -1,167 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -#define local static - -local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - -#define BASE 65521 /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware -- - try it both ways to see which is faster */ -#ifdef NO_DIVIDE -/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 - (thank you to John Reiser for pointing this out) */ -# define CHOP(a) \ - do { \ - unsigned long tmp = a >> 16; \ - a &= 0xffffUL; \ - a += (tmp << 4) - tmp; \ - } while (0) -# define MOD28(a) \ - do { \ - CHOP(a); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD(a) \ - do { \ - CHOP(a); \ - MOD28(a); \ - } while (0) -# define MOD63(a) \ - do { /* this assumes a is not negative */ \ - z_off64_t tmp = a >> 32; \ - a &= 0xffffffffL; \ - a += (tmp << 8) - (tmp << 5) + tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD28(a) a %= BASE -# define MOD63(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* for negative len, return invalid adler32 as a clue for debugging */ - if (len2 < 0) - return 0xffffffffUL; - - /* the derivation of this formula is left as an exercise for the reader */ - MOD63(len2); /* assumes len2 >= 0 */ - rem = (unsigned)len2; - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 >= BASE) sum1 -= BASE; - if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 >= BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) -{ - return adler32_combine_(adler1, adler2, len2); -} - -uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) -{ - return adler32_combine_(adler1, adler2, len2); -} diff --git a/builtins/zlib/adler32_cf.c b/builtins/zlib/adler32_cf.c deleted file mode 100644 index 7cbf8a030a941..0000000000000 --- a/builtins/zlib/adler32_cf.c +++ /dev/null @@ -1,467 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - - -#include "zutil.h" - -#if defined(_MSC_VER) - /* Microsoft C/C++-compatible compiler */ - #include -#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) - /* GCC-compatible compiler, targeting x86/x86-64 */ - #include -#elif defined(__GNUC__) && defined(__ARM_NEON__) - /* GCC-compatible compiler, targeting ARM with NEON */ - #include -#elif defined(__GNUC__) && defined(__IWMMXT__) - /* GCC-compatible compiler, targeting ARM with WMMX */ - #include -#elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__)) - /* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ - #include -#elif defined(__GNUC__) && defined(__SPE__) - /* GCC-compatible compiler, targeting PowerPC with SPE */ - #include -#elif defined(__clang__) && defined(__linux__) - #include -#endif - -#if defined (__x86_64__) && defined (__linux__) -#include "cpuid.h" -#endif - -// from cpuid.h -#ifndef bit_AVX2 -#define bit_AVX2 0x00000020 -#endif - -#ifndef bit_SSE4_2 -# define bit_SSE4_2 0x100000 -#endif - -static uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - -#define BASE 65521 /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -/* - * As we are using _signed_ integer arithmetic for the SSE/AVX2 implementations, - * we consider the max as 2^31-1 - */ -#define NMAX_VEC 5552 - -#define NMAX_VEC2 5552 - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware -- - try it both ways to see which is faster */ -#ifdef NO_DIVIDE -/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 - (thank you to John Reiser for pointing this out) */ -# define CHOP(a) \ - do { \ - unsigned long tmp = a >> 16; \ - a &= 0xffffUL; \ - a += (tmp << 4) - tmp; \ - } while (0) -# define MOD28(a) \ - do { \ - CHOP(a); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD(a) \ - do { \ - CHOP(a); \ - MOD28(a); \ - } while (0) -# define MOD63(a) \ - do { /* this assumes a is not negative */ \ - z_off64_t tmp = a >> 32; \ - a &= 0xffffffffL; \ - a += (tmp << 8) - (tmp << 5) + tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD28(a) a %= BASE -# define MOD63(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32_default(uLong adler, const Bytef *buf, uInt len) -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -#if defined (__x86_64__) && defined (__linux__) && ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) || (__clang__)) - -#ifdef _MSC_VER - -/* MSC doesn't have __builtin_expect. Just ignore likely/unlikely and - hope the compiler optimizes for the best. -*/ -#define likely(x) (x) -#define unlikely(x) (x) - -#else - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - -#endif - -/* ========================================================================= */ - __attribute__ ((target ("sse4.2"))) -uLong ZEXPORT adler32_sse42(uLong adler, const Bytef *buf, uInt len) -{ - unsigned long sum2; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (unlikely(len == 1)) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (unlikely(buf == Z_NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (unlikely(len < 16)) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - uint32_t __attribute__ ((aligned(16))) s1[4], s2[4]; - s1[0] = s1[1] = s1[2] = 0; s1[3] = adler; - s2[0] = s2[1] = s2[2] = 0; s2[3] = sum2; - char __attribute__ ((aligned(16))) dot1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m128i dot1v = _mm_load_si128((__m128i*)dot1); - char __attribute__ ((aligned(16))) dot2[16] = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - __m128i dot2v = _mm_load_si128((__m128i*)dot2); - short __attribute__ ((aligned(16))) dot3[8] = {1, 1, 1, 1, 1, 1, 1, 1}; - __m128i dot3v = _mm_load_si128((__m128i*)dot3); - // We will need to multiply by - //char __attribute__ ((aligned(16))) shift[4] = {0, 0, 0, 4}; //{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}; - char __attribute__ ((aligned(16))) shift[16] = {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - __m128i shiftv = _mm_load_si128((__m128i*)shift); - while (len >= 16) { - __m128i vs1 = _mm_load_si128((__m128i*)s1); - __m128i vs2 = _mm_load_si128((__m128i*)s2); - __m128i vs1_0 = vs1; - int k = (len < NMAX_VEC ? (int)len : NMAX_VEC); - k -= k % 16; - len -= k; - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - - NOTE: 256-bit equivalents are: - _mm256_maddubs_epi16 <- operates on 32 bytes to 16 shorts - _mm256_madd_epi16 <- Sums 16 shorts to 8 int32_t. - We could rewrite the below to use 256-bit instructions instead of 128-bit. - */ - __m128i vbuf = _mm_loadu_si128((__m128i*)buf); - buf += 16; - k -= 16; - __m128i v_short_sum1 = _mm_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 8 shorts. - __m128i vsum1 = _mm_madd_epi16(v_short_sum1, dot3v); // sum 8 shorts to 4 int32_t; - __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - vs1 = _mm_add_epi32(vsum1, vs1); - __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm_sll_epi32(vs1_0, shiftv); - vsum2 = _mm_add_epi32(vsum2, vs2); - vs2 = _mm_add_epi32(vsum2, vs1_0); - vs1_0 = vs1; - } - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - uint32_t __attribute__((aligned(16))) s1_unpack[4]; - uint32_t __attribute__((aligned(16))) s2_unpack[4]; - _mm_store_si128((__m128i*)s1_unpack, vs1); - _mm_store_si128((__m128i*)s2_unpack, vs2); - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE); - MOD(adler); - s1[3] = adler; - sum2 = (s2_unpack[0] % BASE) + (s2_unpack[1] % BASE) + (s2_unpack[2] % BASE) + (s2_unpack[3] % BASE); - MOD(sum2); - s2[3] = sum2; - } - - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - - /* return recombined sums */ - return adler | (sum2 << 16); -} -#ifndef ROOT_NO_AVX2 -/* ========================================================================= */ -__attribute__ ((target ("avx2"))) -uLong ZEXPORT adler32_avx2(uLong adler, const Bytef *buf, uInt len) -{ - unsigned long sum2; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (unlikely(len == 1)) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (unlikely(buf == Z_NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (unlikely(len < 32)) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - uint32_t __attribute__ ((aligned(32))) s1[8], s2[8]; - memset(s1, '\0', sizeof(uint32_t)*7); s1[7] = adler; // TODO: would a masked load be faster? - memset(s2, '\0', sizeof(uint32_t)*7); s2[7] = sum2; - char __attribute__ ((aligned(32))) dot1[32] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m256i dot1v = _mm256_load_si256((__m256i*)dot1); - char __attribute__ ((aligned(32))) dot2[32] = {32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - __m256i dot2v = _mm256_load_si256((__m256i*)dot2); - short __attribute__ ((aligned(32))) dot3[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m256i dot3v = _mm256_load_si256((__m256i*)dot3); - // We will need to multiply by - char __attribute__ ((aligned(16))) shift[16] = {5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - __m128i shiftv = _mm_load_si128((__m128i*)shift); - while (len >= 32) { - __m256i vs1 = _mm256_load_si256((__m256i*)s1); - __m256i vs2 = _mm256_load_si256((__m256i*)s2); - __m256i vs1_0 = vs1; - int k = (len < NMAX_VEC ? (int)len : NMAX_VEC); - k -= k % 32; - len -= k; - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - __m256i vbuf = _mm256_loadu_si256((__m256i*)buf); - buf += 32; - k -= 32; - __m256i v_short_sum1 = _mm256_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 8 shorts. - __m256i vsum1 = _mm256_madd_epi16(v_short_sum1, dot3v); // sum 8 shorts to 4 int32_t; - __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); - vs1 = _mm256_add_epi32(vsum1, vs1); - __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm256_sll_epi32(vs1_0, shiftv); - vsum2 = _mm256_add_epi32(vsum2, vs2); - vs2 = _mm256_add_epi32(vsum2, vs1_0); - vs1_0 = vs1; - } - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - uint32_t __attribute__((aligned(32))) s1_unpack[8]; - uint32_t __attribute__((aligned(32))) s2_unpack[8]; - _mm256_store_si256((__m256i*)s1_unpack, vs1); - _mm256_store_si256((__m256i*)s2_unpack, vs2); - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); - MOD(adler); - s1[7] = adler; - sum2 = (s2_unpack[0] % BASE) + (s2_unpack[1] % BASE) + (s2_unpack[2] % BASE) + (s2_unpack[3] % BASE) + (s2_unpack[4] % BASE) + (s2_unpack[5] % BASE) + (s2_unpack[6] % BASE) + (s2_unpack[7] % BASE); - MOD(sum2); - s2[7] = sum2; - } - - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - - /* return recombined sums */ - return adler | (sum2 << 16); -} -#endif - -void *resolve_adler32(void) -{ - unsigned int eax, ebx, ecx, edx; - signed char has_sse42 = 0; - - /* Collect CPU features */ - if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) - return adler32_default; - - has_sse42 = ((ecx & bit_SSE4_2) != 0); - if (__get_cpuid_max (0, NULL) < 7) - return adler32_default; - - __cpuid_count (7, 0, eax, ebx, ecx, edx); - /* Pick AVX2 version only if as supports AVX2 (not the case of Haswell)*/ -#if !defined(ROOT_NO_AVX2) - signed char has_avx2 = 0; - has_avx2 = ((ebx & bit_AVX2) != 0); - if (has_avx2) - return adler32_avx2; -#endif - /* Pick SSE4.2 version */ - if (has_sse42) - return adler32_sse42; - /* Fallback to default implementation */ - return adler32_default; -} - -uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) __attribute__ ((ifunc ("resolve_adler32"))); - -#else // x86_64 -uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len){ - return adler32_default(adler, buf, len); -} -#endif - -/* ========================================================================= */ -static uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* for negative len, return invalid adler32 as a clue for debugging */ - if (len2 < 0) - return 0xffffffffUL; - - /* the derivation of this formula is left as an exercise for the reader */ - MOD63(len2); /* assumes len2 >= 0 */ - rem = (unsigned)len2; - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 >= BASE) sum1 -= BASE; - if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 >= BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} - -/* ========================================================================= */ -uLong adler32_combine(uLong adler1, uLong adler2, z_off_t len2) -{ - return adler32_combine_(adler1, adler2, len2); -} - -uLong adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) -{ - return adler32_combine_(adler1, adler2, len2); -} diff --git a/builtins/zlib/compress.c b/builtins/zlib/compress.c deleted file mode 100644 index 0aa12f0c3c669..0000000000000 --- a/builtins/zlib/compress.c +++ /dev/null @@ -1,70 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) -{ - z_stream stream; - int err; - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =========================================================================== - */ -int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -uLong ZEXPORT compressBound (uLong sourceLen) -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13; -} diff --git a/builtins/zlib/crc32.c b/builtins/zlib/crc32.c deleted file mode 100644 index 2dcbf7a851708..0000000000000 --- a/builtins/zlib/crc32.c +++ /dev/null @@ -1,401 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id$ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - - DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. - */ - -#ifdef MAKECRCH -# include -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -#define local static - -/* Definitions for doing the crc four data bytes at a time. */ -#if !defined(NOBYFOUR) && defined(Z_U4) -# define BYFOUR -#endif -#ifdef BYFOUR - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); -# define TBLS 8 -#else -# define TBLS 1 -#endif /* BYFOUR */ - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); - - -#ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local z_crc_t FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); -#ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *)); -#endif /* MAKECRCH */ -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - z_crc_t c; - int n, k; - z_crc_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (z_crc_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (z_crc_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } - -#ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const z_crc_t FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH -local void write_table(FILE *out, const z_crc_t FAR *table) -{ - int n; - - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} -#endif /* MAKECRCH */ - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - return (const z_crc_t FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len) -{ - if (buf == Z_NULL) return 0UL; - -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - z_crc_t endian; - - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -#ifdef BYFOUR - -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len) -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = (z_crc_t)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, unsigned len) -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = ZSWAP32((z_crc_t)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf4++; - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(ZSWAP32(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec) -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(unsigned long *square, unsigned long *mat) -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2) -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) -{ - return crc32_combine_(crc1, crc2, len2); -} - -uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) -{ - return crc32_combine_(crc1, crc2, len2); -} diff --git a/builtins/zlib/crc32.h b/builtins/zlib/crc32.h deleted file mode 100644 index 9e0c778102514..0000000000000 --- a/builtins/zlib/crc32.h +++ /dev/null @@ -1,441 +0,0 @@ -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const z_crc_t FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; diff --git a/builtins/zlib/crc32_cf.c b/builtins/zlib/crc32_cf.c deleted file mode 100644 index c4392bb842b5b..0000000000000 --- a/builtins/zlib/crc32_cf.c +++ /dev/null @@ -1,474 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id$ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - - DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. - */ -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC push_options -#if __ARM_ARCH >= 8 -#pragma GCC target ("arch=armv8-a+crc") -#endif -#endif - -#if defined (__ARM_FEATURE_CRC32) -#include -#include - -#include -#include - -uint32_t crc32(uint32_t crc, uint8_t *buf, size_t len) { - crc = ~crc; - - while (len > 8) { - crc = __crc32d(crc, *(uint64_t*)buf); - len -= 8; - buf += 8; - } - - while (len) { - crc = __crc32b(crc, *buf); - len--; - buf++; - } - - return ~crc; -} - -#else - -#include - -#ifdef MAKECRCH -# include -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -#ifdef __x86_64__ -#include "cpuid.h" -#endif - -#define local static - -/* Definitions for doing the crc four data bytes at a time. */ -#if !defined(NOBYFOUR) && defined(Z_U4) -# define BYFOUR -#endif -#ifdef BYFOUR - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); -# define TBLS 8 -#else -# define TBLS 1 -#endif /* BYFOUR */ - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); - - -#ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local z_crc_t FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); -#ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *)); -#endif /* MAKECRCH */ -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - z_crc_t c; - int n, k; - z_crc_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (z_crc_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (z_crc_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } - -#ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const z_crc_t FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH -local void write_table(out, table) - FILE *out; - const z_crc_t FAR *table; -{ - int n; - - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} -#endif /* MAKECRCH */ - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - return (const z_crc_t FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -local unsigned long crc32_generic(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - uInt len; -{ - if (buf == Z_NULL) return 0UL; - -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - z_crc_t endian; - - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -uLong crc32(crc, buf, len) - uLong crc; - const Bytef *buf; - uInt len; -{ - return crc32_generic(crc, buf, len); -} - -#ifdef BYFOUR - -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = (z_crc_t)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = ZSWAP32((z_crc_t)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf4++; - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(ZSWAP32(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(mat, vec) - unsigned long *mat; - unsigned long vec; -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(square, mat) - unsigned long *square; - unsigned long *mat; -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -local uLong crc32_combine_(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ - return crc32_combine_(crc1, crc2, len2); -} - -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ - return crc32_combine_(crc1, crc2, len2); -} - -#endif diff --git a/builtins/zlib/deflate.c b/builtins/zlib/deflate.c deleted file mode 100644 index d56571b143359..0000000000000 --- a/builtins/zlib/deflate.c +++ /dev/null @@ -1,1907 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id$ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -#ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -#ifdef FASTEST -local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ -#else -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -#endif - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - -/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, - const char *version, int stream_size) -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } -#ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } -#endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->high_water = 0; /* nothing written to s->window yet */ - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) -{ - deflate_state *s; - uInt str, n; - int wrap; - unsigned avail; - z_const unsigned char *next; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) - return Z_STREAM_ERROR; - s = strm->state; - wrap = s->wrap; - if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) - return Z_STREAM_ERROR; - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap == 1) - strm->adler = adler32(strm->adler, dictionary, dictLength); - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s->w_size) { - if (wrap == 0) { /* already empty otherwise */ - CLEAR_HASH(s); - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - dictionary += dictLength - s->w_size; /* use the tail */ - dictLength = s->w_size; - } - - /* insert dictionary into window and hash */ - avail = strm->avail_in; - next = strm->next_in; - strm->avail_in = dictLength; - strm->next_in = (z_const Bytef *)dictionary; - fill_window(s); - while (s->lookahead >= MIN_MATCH) { - str = s->strstart; - n = s->lookahead - (MIN_MATCH-1); - do { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - } while (--n); - s->strstart = str; - s->lookahead = MIN_MATCH-1; - fill_window(s); - } - s->strstart += s->lookahead; - s->block_start = (long)s->strstart; - s->insert = s->lookahead; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - strm->next_in = next; - strm->avail_in = avail; - s->wrap = wrap; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateResetKeep (z_streamp strm) -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = -#ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : -#endif - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (z_streamp strm) -{ - int ret; - - ret = deflateResetKeep(strm); - if (ret == Z_OK) - lm_init(strm->state); - return ret; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head) -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePending (z_streamp strm, unsigned *pending, int *bits) -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (pending != Z_NULL) - *pending = strm->state->pending; - if (bits != Z_NULL) - *bits = strm->state->bi_valid; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime (z_streamp strm, int bits, int value) -{ - deflate_state *s; - int put; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) - return Z_BUF_ERROR; - do { - put = Buf_size - s->bi_valid; - if (put > bits) - put = bits; - s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); - s->bi_valid += put; - _tr_flush_bits(s); - value >>= put; - bits -= put; - } while (bits); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); - if (err == Z_BUF_ERROR && s->pending == 0) - err = Z_OK; - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; - s->nice_match = nice_length; - s->max_chain_length = max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. - */ -uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) -{ - deflate_state *s; - uLong complen, wraplen; - Bytef *str; - - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; - - /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) - return complen + 6; - - /* compute wrapper length */ - s = strm->state; - switch (s->wrap) { - case 0: /* raw deflate */ - wraplen = 0; - break; - case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); - break; - case 2: /* gzip wrapper */ - wraplen = 18; - if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ - if (s->gzhead->extra != Z_NULL) - wraplen += 2 + s->gzhead->extra_len; - str = s->gzhead->name; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - str = s->gzhead->comment; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - if (s->gzhead->hcrc) - wraplen += 2; - } - break; - default: /* for compiler happiness */ - wraplen = 6; - } - - /* if not default parameters, return conservative bound */ - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; - - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13 - 6 + wraplen; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (deflate_state *s, uInt b) -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending(z_streamp strm) -{ - unsigned len; - deflate_state *s = strm->state; - - _tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) { - s->pending_out = s->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate (z_streamp strm, int flush) -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - if (s->lookahead == 0) { - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else -#endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (z_streamp strm) -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif /* MAXSEG_64K */ -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(z_streamp strm, Bytef *buf, unsigned size) -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } -#endif - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (deflate_state *s) -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif -} - -#ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match(deflate_state *s, IPos cur_match) -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} -#endif /* ASMV */ - -#else /* FASTEST */ - -/* --------------------------------------------------------------------------- - * Optimized version for FASTEST only - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#endif /* FASTEST */ - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(deflate_state *s) -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - UPDATE_HASH(s, s->ins_h, s->window[str + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - while (s->insert) { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, last) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (last)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, last) { \ - FLUSH_BLOCK_ONLY(s, last); \ - if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored(deflate_state *s, int flush) -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if ((long)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(deflate_state *s, int flush) -{ - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -#ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(deflate_state *s, int flush) -{ - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -#if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) -#endif - )) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} -#endif /* FASTEST */ - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -local block_state deflate_rle(deflate_state *s, int flush) -{ - int bflush; /* set if current block must be flushed */ - uInt prev; /* byte at distance one to match */ - Bytef *scan, *strend; /* scan goes up to strend for length of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s->match_length = 0; - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); - if (s->match_length > s->lookahead) - s->match_length = s->lookahead; - } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, s->match_length); - - _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - s->strstart += s->match_length; - s->match_length = 0; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -local block_state deflate_huff(deflate_state *s, int flush) -{ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s->match_length = 0; - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/builtins/zlib/deflate.h b/builtins/zlib/deflate.h deleted file mode 100644 index ce0299edd1916..0000000000000 --- a/builtins/zlib/deflate.h +++ /dev/null @@ -1,346 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define Buf_size 16 -/* size of bit buffer in bi_buf */ - -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* can only be DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - uInt insert; /* bytes at end of window left to insert */ - -#ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - ulg high_water; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -#define WIN_INIT MAX_MATCH -/* Number of bytes after end of data in window to initialize in order to avoid - memory checker errors from longest match routines */ - - /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch ZLIB_INTERNAL _length_code[]; - extern uch ZLIB_INTERNAL _dist_code[]; -#else - extern const uch ZLIB_INTERNAL _length_code[]; - extern const uch ZLIB_INTERNAL _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif /* DEFLATE_H */ diff --git a/builtins/zlib/deflate_cf.c b/builtins/zlib/deflate_cf.c deleted file mode 100644 index 54aebec62a838..0000000000000 --- a/builtins/zlib/deflate_cf.c +++ /dev/null @@ -1,3211 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -#if defined(__cplusplus) -#define UNUSED(x) // = nothing -#elif defined(__GNUC__) -#define UNUSED(x) x##_UNUSED __attribute__((unused)) -#else -#define UNUSED(x) x##_UNUSED -#endif - -/* @(#) $Id$ */ - -#include "deflate_cf.h" - -#ifdef __x86_64__ -#include "cpuid.h" -#endif - -#if defined(_MSC_VER) - /* Microsoft C/C++-compatible compiler */ - #include -#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) - /* GCC-compatible compiler, targeting x86/x86-64 */ - #include -#elif defined(__GNUC__) && defined(__ARM_NEON__) - /* GCC-compatible compiler, targeting ARM with NEON */ - #include -#elif defined(__GNUC__) && defined(__IWMMXT__) - /* GCC-compatible compiler, targeting ARM with WMMX */ - #include -#elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__)) - /* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ - #include -#elif defined(__GNUC__) && defined(__SPE__) - /* GCC-compatible compiler, targeting PowerPC with SPE */ - #include -#elif defined(__clang__) && defined(__linux__) - #include -#endif - -const char deflate_copyright[] = - " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func)(deflate_state *s, int flush); -/* Compression function. Returns the block state after the call. */ - -static void fill_window(deflate_state *s); -static block_state deflate_stored(deflate_state *s, int flush); -static block_state deflate_fast(deflate_state *s, int flush); -static block_state deflate_slow(deflate_state *s, int flush); -static block_state deflate_rle(deflate_state *s, int flush); -static block_state deflate_huff(deflate_state *s, int flush); -static void lm_init(deflate_state *s); -static void putShortMSB(deflate_state *s, uint32_t b); -static void flush_pending(z_streamp strm); -static int read_buf(z_streamp strm, uint8_t *buf, uint32_t size); - -#ifdef DEBUG -static void check_match(deflate_state *s, IPos start, IPos match, - int length); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ -#define ACTUAL_MIN_MATCH 4 -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - uint16_t good_length; /* reduce lazy search above this match length */ - uint16_t max_lazy; /* do not perform lazy search above this match length */ - uint16_t nice_length; /* quit search above this match length */ - uint16_t max_chain; - compress_func func; -} config; - -static const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) - -// ////////////////////////////////////////////////////////// -// Crc32.h -// Copyright (c) 2011-2016 Stephan Brumme. All rights reserved. -// Slicing-by-16 contributed by Bulat Ziganshin -// Tableless bytewise CRC contributed by Hagai Gold -// see http://create.stephan-brumme.com/disclaimer.html -// - -#ifdef _MSC_VER -#define PREFETCH(location) _mm_prefetch(location, _MM_HINT_T0) -#else -#ifdef __GNUC__ -#define PREFETCH(location) __builtin_prefetch(location) -#else -#define PREFETCH(location); -#endif -#endif - -// zlib's CRC32 polynomial -const uint32_t Polynomial = 0xEDB88320; - -/// swap endianess -static inline uint32_t swap(uint32_t x) -{ -#if defined(__GNUC__) || defined(__clang__) - return __builtin_bswap32(x); -#else - return (x >> 24) | - ((x >> 8) & 0x0000FF00) | - ((x << 8) & 0x00FF0000) | - (x << 24); -#endif -} - -/// Slicing-By-16 -#define MaxSlice 16 - -/// look-up table, already declared above -const uint32_t Crc32Lookup[MaxSlice][256] = -{ - //// same algorithm as crc32_bitwise - //for (int i = 0; i <= 0xFF; i++) - //{ - // uint32_t crc = i; - // for (int j = 0; j < 8; j++) - // crc = (crc >> 1) ^ ((crc & 1) * Polynomial); - // Crc32Lookup[0][i] = crc; - //} - //// ... and the following slicing-by-8 algorithm (from Intel): - //// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf - //// http://sourceforge.net/projects/slicing-by-8/ - //for (int slice = 1; slice < MaxSlice; slice++) - // Crc32Lookup[slice][i] = (Crc32Lookup[slice - 1][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[slice - 1][i] & 0xFF]; - { - // note: the first number of every second row corresponds to the half-byte look-up table ! - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, - }, - - // beyond this point only relevant for Slicing-by-4, Slicing-by-8 and Slicing-by-16 - { - 0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7, - 0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF, - 0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192, 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496, - 0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A, 0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, - 0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761, 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, - 0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69, 0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D, - 0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034, - 0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, 0x73F379FF, 0x6AE848BE, 0x41C51B7D, 0x58DE2A3C, - 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2, - 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA, - 0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97, 0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, - 0x7262D75C, 0x6B79E61D, 0x4054B5DE, 0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, - 0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, 0x4ED03864, 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, - 0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C, 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768, - 0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, 0x4B53BCF2, 0x52488DB3, 0x7965DE70, 0x607EEF31, - 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB, 0xB1BC5478, 0xA8A76539, - 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, 0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, 0x74C20E8C, - 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180, 0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, - 0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, - 0xB9980012, 0xA0833153, 0x8BAE6290, 0x92B553D1, 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, - 0xAE07BCE9, 0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E, - 0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026, - 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, 0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F, - 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, 0x4870E1B4, 0x516BD0F5, 0x7A468336, 0x635DB277, - 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D, 0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189, - 0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85, 0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81, - 0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, - 0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0, - 0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F, 0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B, - 0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23, - 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, 0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A, - 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876, 0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72, - }, - - { - 0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685, - 0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D, - 0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5, - 0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91, 0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, - 0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9, 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, - 0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901, 0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD, - 0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315, - 0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, 0x2F37A2AD, - 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45, - 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, - 0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9, 0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, - 0x62AF7F08, 0x636D153F, 0x612BAB66, 0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, - 0x48D7CB20, 0x4915A117, 0x4B531F4E, 0x4A917579, 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, - 0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1, 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D, - 0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, 0x53F8C08C, 0x523AAABB, 0x507C14E2, 0x51BE7ED5, - 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03, 0x5E6F455A, 0x5FAD2F6D, - 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, 0xE63CB35C, 0xE7FED96B, 0xE5B86732, 0xE47A0D05, - 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461, 0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, - 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, - 0xF300E948, 0xF2C2837F, 0xF0843D26, 0xF1465711, 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, - 0xD9785D60, 0xD8BA3757, 0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5, - 0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281, 0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D, - 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, 0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895, - 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, 0xCC440774, 0xCD866D43, 0xCFC0D31A, 0xCE02B92D, - 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819, 0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5, - 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1, 0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D, - 0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, - 0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D, - 0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9, 0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625, - 0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D, - 0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, 0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555, - 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31, 0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED, - }, - - { - 0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9, - 0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056, - 0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871, 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26, - 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E, 0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, - 0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0, 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, - 0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F, 0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68, - 0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018, - 0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, 0xBAFD4719, 0x0241207C, 0x10F48F92, 0xA848E8F7, - 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084, - 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B, - 0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C, 0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, - 0x0EB9274D, 0xB6054028, 0xA4B0EFC6, 0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, - 0x3B26F703, 0x839A9066, 0x912F3F88, 0x299358ED, 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, - 0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002, 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755, - 0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, 0xE45D37CB, 0x5CE150AE, 0x4E54FF40, 0xF6E89825, - 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841, 0x8BE0D7AF, 0x335CB0CA, - 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, 0x623B216C, 0xDA874609, 0xC832E9E7, 0x708E8E82, - 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A, 0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, - 0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A, 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, - 0x78F4C94B, 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5, 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, - 0x4D6B1905, 0xF5D77E60, 0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC, - 0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953, - 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, 0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623, - 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, 0x57A4F122, 0xEF189647, 0xFDAD39A9, 0x45115ECC, - 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8, 0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF, - 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907, 0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50, - 0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, - 0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF, - 0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, 0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981, - 0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E, - 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, 0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E, - 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6, 0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1, - }, - - // beyond this point only relevant for Slicing-by-8 and Slicing-by-16 - { - 0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10, - 0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, 0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1, - 0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52, 0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92, - 0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693, 0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053, - 0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4, 0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, - 0xF1B164C5, 0xCCD14D75, 0x8B7137A5, 0xB6111E15, 0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5, - 0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256, 0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496, - 0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, 0x64D15587, 0x59B17C37, 0x1E1106E7, 0x23712F57, - 0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299, 0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459, - 0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, 0x9D03B548, 0xA0639CF8, 0xE7C3E628, 0xDAA3CF98, - 0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B, 0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, - 0x0863840A, 0x3503ADBA, 0x72A3D76A, 0x4FC3FEDA, 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, - 0x9932774D, 0xA4525EFD, 0xE3F2242D, 0xDE920D9D, 0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D, - 0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C, 0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C, - 0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F, 0x0C52460F, 0x31326FBF, 0x7692156F, 0x4BF23CDF, - 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, 0x3C220DCE, 0x0142247E, 0x46E25EAE, 0x7B82771E, - 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, 0x44661652, 0x79063FE2, 0x3EA64532, 0x03C66C82, - 0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183, 0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743, - 0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0, 0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00, - 0xE1766CD1, 0xDC164561, 0x9BB63FB1, 0xA6D61601, 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, - 0x70279F96, 0x4D47B626, 0x0AE7CCF6, 0x3787E546, 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386, - 0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87, 0xB5D77297, 0x88B75B27, 0xCF1721F7, 0xF2770847, - 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4, 0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404, - 0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905, 0xD537E515, 0xE857CCA5, 0xAFF7B675, 0x92979FC5, - 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B, 0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB, - 0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA, 0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A, - 0x89F57F59, 0xB49556E9, 0xF3352C39, 0xCE550589, 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349, - 0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48, 0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888, - 0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F, 0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF, - 0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E, - 0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, 0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D, - 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C, 0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C, - }, - - { - 0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8, - 0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, 0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5, - 0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035, 0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223, - 0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258, 0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E, - 0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798, 0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, - 0xEBFF875B, 0x20A354FE, 0xA6372650, 0x6D6BF5F5, 0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, - 0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503, 0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715, - 0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, 0x73B8C7D6, 0xB8E41473, 0x3E7066DD, 0xF52CB578, - 0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2, 0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4, - 0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, 0x789ACA17, 0xB3C619B2, 0x35526B1C, 0xFE0EB8B9, - 0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59, 0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, - 0xE0DD8A9A, 0x2B81593F, 0xAD152B91, 0x6649F834, 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, - 0x08F40F5A, 0xC3A8DCFF, 0x453CAE51, 0x8E607DF4, 0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2, - 0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99, 0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F, - 0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F, 0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC, 0x16273D79, - 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, 0x7CE0CDBA, 0xB7BC1E1F, 0x31286CB1, 0xFA74BF14, - 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, 0x852156CE, 0x4E7D856B, 0xC8E9F7C5, 0x03B52460, - 0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B, 0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D, - 0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED, 0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB, - 0xF135942E, 0x3A69478B, 0xBCFD3525, 0x77A1E680, 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, - 0x191C11EE, 0xD240C24B, 0x54D4B0E5, 0x9F886340, 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156, - 0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D, 0x6EDED195, 0xA5820230, 0x2316709E, 0xE84AA33B, - 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB, 0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD, - 0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6, 0x6D08D30E, 0xA65400AB, 0x20C07205, 0xEB9CA1A0, - 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A, 0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C, - 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77, 0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61, - 0x123E1C2F, 0xD962CF8A, 0x5FF6BD24, 0x94AA6E81, 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97, - 0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC, 0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA, - 0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C, 0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A, - 0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957, - 0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, 0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1, - 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA, 0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC, - }, - - { - 0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E, - 0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, 0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9, - 0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653, 0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240, - 0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834, 0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27, - 0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301, 0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, - 0xFC5277FB, 0x5A257C4F, 0x6BCD66D2, 0xCDBA6D66, 0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975, - 0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, 0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC, - 0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F, 0x5E2BD5BB, - 0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4, 0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7, - 0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, 0x83AB1F0D, 0x25DC14B9, 0x14340E24, 0xB2430590, - 0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A, 0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, - 0x103AA7D0, 0xB64DAC64, 0x87A5B6F9, 0x21D2BD4D, 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, - 0x8BB64CE5, 0x2DC14751, 0x1C295DCC, 0xBA5E5678, 0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B, - 0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F, 0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C, - 0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6, 0x1827F438, 0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5, - 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, 0x2BC8BA5F, 0x8DBFB1EB, 0xBC57AB76, 0x1A20A0C2, - 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, 0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C, - 0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08, 0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B, - 0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1, 0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2, - 0xDC27385B, 0x7A5033EF, 0x4BB82972, 0xEDCF22C6, 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, - 0x47ABD36E, 0xE1DCD8DA, 0xD034C247, 0x7643C9F3, 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0, - 0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794, 0x800BB91A, 0x267CB2AE, 0x1794A833, 0xB1E3A387, - 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D, 0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E, - 0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A, 0xE7D525D4, 0x41A22E60, 0x704A34FD, 0xD63D3F49, - 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516, 0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105, - 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71, 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62, - 0xABC30345, 0x0DB408F1, 0x3C5C126C, 0x9A2B19D8, 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB, - 0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, 0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC, - 0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, 0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899, - 0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE, - 0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, 0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457, - 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23, 0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30, - }, - - { - 0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919, - 0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, 0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC, - 0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8, 0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832, - 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D, 0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387, - 0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5, 0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, - 0x2A9379E3, 0xE639797D, 0x68B67E9E, 0xA41C7E00, 0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA, - 0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E, 0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64, - 0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, 0xD2624632, 0x1EC846AC, 0x9047414F, 0x5CED41D1, - 0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E, 0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4, - 0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, 0x7E32D7A2, 0xB298D73C, 0x3C17D0DF, 0xF0BDD041, - 0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425, 0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, - 0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E, 0x084CEF90, 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, - 0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6, 0x5E64A758, 0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2, - 0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED, 0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217, - 0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673, 0x281A9F6A, 0xE4B09FF4, 0x6A3F9817, 0xA6959889, - 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, 0xFBFF84DF, 0x37558441, 0xB9DA83A2, 0x7570833C, - 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, 0xD7718B20, 0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3, - 0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C, 0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776, - 0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312, 0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8, - 0xFC65AF44, 0x30CFAFDA, 0xBE40A839, 0x72EAA8A7, 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, - 0xAA4DE78C, 0x66E7E712, 0xE868E0F1, 0x24C2E06F, 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95, - 0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA, 0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE, 0x736DF520, - 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144, 0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE, - 0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1, 0x8159C3E8, 0x4DF3C376, 0xC37CC495, 0x0FD6C40B, - 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4, 0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E, - 0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61, 0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B, - 0x061D761C, 0xCAB77682, 0x44387161, 0x889271FF, 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05, - 0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A, 0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0, - 0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, 0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78, - 0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD, - 0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, 0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53, - 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C, 0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6, - }, - - // beyond this point only relevant for Slicing-by-16 - { - 0x00000000, 0x177B1443, 0x2EF62886, 0x398D3CC5, 0x5DEC510C, 0x4A97454F, 0x731A798A, 0x64616DC9, - 0xBBD8A218, 0xACA3B65B, 0x952E8A9E, 0x82559EDD, 0xE634F314, 0xF14FE757, 0xC8C2DB92, 0xDFB9CFD1, - 0xACC04271, 0xBBBB5632, 0x82366AF7, 0x954D7EB4, 0xF12C137D, 0xE657073E, 0xDFDA3BFB, 0xC8A12FB8, - 0x1718E069, 0x0063F42A, 0x39EEC8EF, 0x2E95DCAC, 0x4AF4B165, 0x5D8FA526, 0x640299E3, 0x73798DA0, - 0x82F182A3, 0x958A96E0, 0xAC07AA25, 0xBB7CBE66, 0xDF1DD3AF, 0xC866C7EC, 0xF1EBFB29, 0xE690EF6A, - 0x392920BB, 0x2E5234F8, 0x17DF083D, 0x00A41C7E, 0x64C571B7, 0x73BE65F4, 0x4A335931, 0x5D484D72, - 0x2E31C0D2, 0x394AD491, 0x00C7E854, 0x17BCFC17, 0x73DD91DE, 0x64A6859D, 0x5D2BB958, 0x4A50AD1B, - 0x95E962CA, 0x82927689, 0xBB1F4A4C, 0xAC645E0F, 0xC80533C6, 0xDF7E2785, 0xE6F31B40, 0xF1880F03, - 0xDE920307, 0xC9E91744, 0xF0642B81, 0xE71F3FC2, 0x837E520B, 0x94054648, 0xAD887A8D, 0xBAF36ECE, - 0x654AA11F, 0x7231B55C, 0x4BBC8999, 0x5CC79DDA, 0x38A6F013, 0x2FDDE450, 0x1650D895, 0x012BCCD6, - 0x72524176, 0x65295535, 0x5CA469F0, 0x4BDF7DB3, 0x2FBE107A, 0x38C50439, 0x014838FC, 0x16332CBF, - 0xC98AE36E, 0xDEF1F72D, 0xE77CCBE8, 0xF007DFAB, 0x9466B262, 0x831DA621, 0xBA909AE4, 0xADEB8EA7, - 0x5C6381A4, 0x4B1895E7, 0x7295A922, 0x65EEBD61, 0x018FD0A8, 0x16F4C4EB, 0x2F79F82E, 0x3802EC6D, - 0xE7BB23BC, 0xF0C037FF, 0xC94D0B3A, 0xDE361F79, 0xBA5772B0, 0xAD2C66F3, 0x94A15A36, 0x83DA4E75, - 0xF0A3C3D5, 0xE7D8D796, 0xDE55EB53, 0xC92EFF10, 0xAD4F92D9, 0xBA34869A, 0x83B9BA5F, 0x94C2AE1C, - 0x4B7B61CD, 0x5C00758E, 0x658D494B, 0x72F65D08, 0x169730C1, 0x01EC2482, 0x38611847, 0x2F1A0C04, - 0x6655004F, 0x712E140C, 0x48A328C9, 0x5FD83C8A, 0x3BB95143, 0x2CC24500, 0x154F79C5, 0x02346D86, - 0xDD8DA257, 0xCAF6B614, 0xF37B8AD1, 0xE4009E92, 0x8061F35B, 0x971AE718, 0xAE97DBDD, 0xB9ECCF9E, - 0xCA95423E, 0xDDEE567D, 0xE4636AB8, 0xF3187EFB, 0x97791332, 0x80020771, 0xB98F3BB4, 0xAEF42FF7, - 0x714DE026, 0x6636F465, 0x5FBBC8A0, 0x48C0DCE3, 0x2CA1B12A, 0x3BDAA569, 0x025799AC, 0x152C8DEF, - 0xE4A482EC, 0xF3DF96AF, 0xCA52AA6A, 0xDD29BE29, 0xB948D3E0, 0xAE33C7A3, 0x97BEFB66, 0x80C5EF25, - 0x5F7C20F4, 0x480734B7, 0x718A0872, 0x66F11C31, 0x029071F8, 0x15EB65BB, 0x2C66597E, 0x3B1D4D3D, - 0x4864C09D, 0x5F1FD4DE, 0x6692E81B, 0x71E9FC58, 0x15889191, 0x02F385D2, 0x3B7EB917, 0x2C05AD54, - 0xF3BC6285, 0xE4C776C6, 0xDD4A4A03, 0xCA315E40, 0xAE503389, 0xB92B27CA, 0x80A61B0F, 0x97DD0F4C, - 0xB8C70348, 0xAFBC170B, 0x96312BCE, 0x814A3F8D, 0xE52B5244, 0xF2504607, 0xCBDD7AC2, 0xDCA66E81, - 0x031FA150, 0x1464B513, 0x2DE989D6, 0x3A929D95, 0x5EF3F05C, 0x4988E41F, 0x7005D8DA, 0x677ECC99, - 0x14074139, 0x037C557A, 0x3AF169BF, 0x2D8A7DFC, 0x49EB1035, 0x5E900476, 0x671D38B3, 0x70662CF0, - 0xAFDFE321, 0xB8A4F762, 0x8129CBA7, 0x9652DFE4, 0xF233B22D, 0xE548A66E, 0xDCC59AAB, 0xCBBE8EE8, - 0x3A3681EB, 0x2D4D95A8, 0x14C0A96D, 0x03BBBD2E, 0x67DAD0E7, 0x70A1C4A4, 0x492CF861, 0x5E57EC22, - 0x81EE23F3, 0x969537B0, 0xAF180B75, 0xB8631F36, 0xDC0272FF, 0xCB7966BC, 0xF2F45A79, 0xE58F4E3A, - 0x96F6C39A, 0x818DD7D9, 0xB800EB1C, 0xAF7BFF5F, 0xCB1A9296, 0xDC6186D5, 0xE5ECBA10, 0xF297AE53, - 0x2D2E6182, 0x3A5575C1, 0x03D84904, 0x14A35D47, 0x70C2308E, 0x67B924CD, 0x5E341808, 0x494F0C4B, - }, - - { - 0x00000000, 0xEFC26B3E, 0x04F5D03D, 0xEB37BB03, 0x09EBA07A, 0xE629CB44, 0x0D1E7047, 0xE2DC1B79, - 0x13D740F4, 0xFC152BCA, 0x172290C9, 0xF8E0FBF7, 0x1A3CE08E, 0xF5FE8BB0, 0x1EC930B3, 0xF10B5B8D, - 0x27AE81E8, 0xC86CEAD6, 0x235B51D5, 0xCC993AEB, 0x2E452192, 0xC1874AAC, 0x2AB0F1AF, 0xC5729A91, - 0x3479C11C, 0xDBBBAA22, 0x308C1121, 0xDF4E7A1F, 0x3D926166, 0xD2500A58, 0x3967B15B, 0xD6A5DA65, - 0x4F5D03D0, 0xA09F68EE, 0x4BA8D3ED, 0xA46AB8D3, 0x46B6A3AA, 0xA974C894, 0x42437397, 0xAD8118A9, - 0x5C8A4324, 0xB348281A, 0x587F9319, 0xB7BDF827, 0x5561E35E, 0xBAA38860, 0x51943363, 0xBE56585D, - 0x68F38238, 0x8731E906, 0x6C065205, 0x83C4393B, 0x61182242, 0x8EDA497C, 0x65EDF27F, 0x8A2F9941, - 0x7B24C2CC, 0x94E6A9F2, 0x7FD112F1, 0x901379CF, 0x72CF62B6, 0x9D0D0988, 0x763AB28B, 0x99F8D9B5, - 0x9EBA07A0, 0x71786C9E, 0x9A4FD79D, 0x758DBCA3, 0x9751A7DA, 0x7893CCE4, 0x93A477E7, 0x7C661CD9, - 0x8D6D4754, 0x62AF2C6A, 0x89989769, 0x665AFC57, 0x8486E72E, 0x6B448C10, 0x80733713, 0x6FB15C2D, - 0xB9148648, 0x56D6ED76, 0xBDE15675, 0x52233D4B, 0xB0FF2632, 0x5F3D4D0C, 0xB40AF60F, 0x5BC89D31, - 0xAAC3C6BC, 0x4501AD82, 0xAE361681, 0x41F47DBF, 0xA32866C6, 0x4CEA0DF8, 0xA7DDB6FB, 0x481FDDC5, - 0xD1E70470, 0x3E256F4E, 0xD512D44D, 0x3AD0BF73, 0xD80CA40A, 0x37CECF34, 0xDCF97437, 0x333B1F09, - 0xC2304484, 0x2DF22FBA, 0xC6C594B9, 0x2907FF87, 0xCBDBE4FE, 0x24198FC0, 0xCF2E34C3, 0x20EC5FFD, - 0xF6498598, 0x198BEEA6, 0xF2BC55A5, 0x1D7E3E9B, 0xFFA225E2, 0x10604EDC, 0xFB57F5DF, 0x14959EE1, - 0xE59EC56C, 0x0A5CAE52, 0xE16B1551, 0x0EA97E6F, 0xEC756516, 0x03B70E28, 0xE880B52B, 0x0742DE15, - 0xE6050901, 0x09C7623F, 0xE2F0D93C, 0x0D32B202, 0xEFEEA97B, 0x002CC245, 0xEB1B7946, 0x04D91278, - 0xF5D249F5, 0x1A1022CB, 0xF12799C8, 0x1EE5F2F6, 0xFC39E98F, 0x13FB82B1, 0xF8CC39B2, 0x170E528C, - 0xC1AB88E9, 0x2E69E3D7, 0xC55E58D4, 0x2A9C33EA, 0xC8402893, 0x278243AD, 0xCCB5F8AE, 0x23779390, - 0xD27CC81D, 0x3DBEA323, 0xD6891820, 0x394B731E, 0xDB976867, 0x34550359, 0xDF62B85A, 0x30A0D364, - 0xA9580AD1, 0x469A61EF, 0xADADDAEC, 0x426FB1D2, 0xA0B3AAAB, 0x4F71C195, 0xA4467A96, 0x4B8411A8, - 0xBA8F4A25, 0x554D211B, 0xBE7A9A18, 0x51B8F126, 0xB364EA5F, 0x5CA68161, 0xB7913A62, 0x5853515C, - 0x8EF68B39, 0x6134E007, 0x8A035B04, 0x65C1303A, 0x871D2B43, 0x68DF407D, 0x83E8FB7E, 0x6C2A9040, - 0x9D21CBCD, 0x72E3A0F3, 0x99D41BF0, 0x761670CE, 0x94CA6BB7, 0x7B080089, 0x903FBB8A, 0x7FFDD0B4, - 0x78BF0EA1, 0x977D659F, 0x7C4ADE9C, 0x9388B5A2, 0x7154AEDB, 0x9E96C5E5, 0x75A17EE6, 0x9A6315D8, - 0x6B684E55, 0x84AA256B, 0x6F9D9E68, 0x805FF556, 0x6283EE2F, 0x8D418511, 0x66763E12, 0x89B4552C, - 0x5F118F49, 0xB0D3E477, 0x5BE45F74, 0xB426344A, 0x56FA2F33, 0xB938440D, 0x520FFF0E, 0xBDCD9430, - 0x4CC6CFBD, 0xA304A483, 0x48331F80, 0xA7F174BE, 0x452D6FC7, 0xAAEF04F9, 0x41D8BFFA, 0xAE1AD4C4, - 0x37E20D71, 0xD820664F, 0x3317DD4C, 0xDCD5B672, 0x3E09AD0B, 0xD1CBC635, 0x3AFC7D36, 0xD53E1608, - 0x24354D85, 0xCBF726BB, 0x20C09DB8, 0xCF02F686, 0x2DDEEDFF, 0xC21C86C1, 0x292B3DC2, 0xC6E956FC, - 0x104C8C99, 0xFF8EE7A7, 0x14B95CA4, 0xFB7B379A, 0x19A72CE3, 0xF66547DD, 0x1D52FCDE, 0xF29097E0, - 0x039BCC6D, 0xEC59A753, 0x076E1C50, 0xE8AC776E, 0x0A706C17, 0xE5B20729, 0x0E85BC2A, 0xE147D714, - }, - - { - 0x00000000, 0xC18EDFC0, 0x586CB9C1, 0x99E26601, 0xB0D97382, 0x7157AC42, 0xE8B5CA43, 0x293B1583, - 0xBAC3E145, 0x7B4D3E85, 0xE2AF5884, 0x23218744, 0x0A1A92C7, 0xCB944D07, 0x52762B06, 0x93F8F4C6, - 0xAEF6C4CB, 0x6F781B0B, 0xF69A7D0A, 0x3714A2CA, 0x1E2FB749, 0xDFA16889, 0x46430E88, 0x87CDD148, - 0x1435258E, 0xD5BBFA4E, 0x4C599C4F, 0x8DD7438F, 0xA4EC560C, 0x656289CC, 0xFC80EFCD, 0x3D0E300D, - 0x869C8FD7, 0x47125017, 0xDEF03616, 0x1F7EE9D6, 0x3645FC55, 0xF7CB2395, 0x6E294594, 0xAFA79A54, - 0x3C5F6E92, 0xFDD1B152, 0x6433D753, 0xA5BD0893, 0x8C861D10, 0x4D08C2D0, 0xD4EAA4D1, 0x15647B11, - 0x286A4B1C, 0xE9E494DC, 0x7006F2DD, 0xB1882D1D, 0x98B3389E, 0x593DE75E, 0xC0DF815F, 0x01515E9F, - 0x92A9AA59, 0x53277599, 0xCAC51398, 0x0B4BCC58, 0x2270D9DB, 0xE3FE061B, 0x7A1C601A, 0xBB92BFDA, - 0xD64819EF, 0x17C6C62F, 0x8E24A02E, 0x4FAA7FEE, 0x66916A6D, 0xA71FB5AD, 0x3EFDD3AC, 0xFF730C6C, - 0x6C8BF8AA, 0xAD05276A, 0x34E7416B, 0xF5699EAB, 0xDC528B28, 0x1DDC54E8, 0x843E32E9, 0x45B0ED29, - 0x78BEDD24, 0xB93002E4, 0x20D264E5, 0xE15CBB25, 0xC867AEA6, 0x09E97166, 0x900B1767, 0x5185C8A7, - 0xC27D3C61, 0x03F3E3A1, 0x9A1185A0, 0x5B9F5A60, 0x72A44FE3, 0xB32A9023, 0x2AC8F622, 0xEB4629E2, - 0x50D49638, 0x915A49F8, 0x08B82FF9, 0xC936F039, 0xE00DE5BA, 0x21833A7A, 0xB8615C7B, 0x79EF83BB, - 0xEA17777D, 0x2B99A8BD, 0xB27BCEBC, 0x73F5117C, 0x5ACE04FF, 0x9B40DB3F, 0x02A2BD3E, 0xC32C62FE, - 0xFE2252F3, 0x3FAC8D33, 0xA64EEB32, 0x67C034F2, 0x4EFB2171, 0x8F75FEB1, 0x169798B0, 0xD7194770, - 0x44E1B3B6, 0x856F6C76, 0x1C8D0A77, 0xDD03D5B7, 0xF438C034, 0x35B61FF4, 0xAC5479F5, 0x6DDAA635, - 0x77E1359F, 0xB66FEA5F, 0x2F8D8C5E, 0xEE03539E, 0xC738461D, 0x06B699DD, 0x9F54FFDC, 0x5EDA201C, - 0xCD22D4DA, 0x0CAC0B1A, 0x954E6D1B, 0x54C0B2DB, 0x7DFBA758, 0xBC757898, 0x25971E99, 0xE419C159, - 0xD917F154, 0x18992E94, 0x817B4895, 0x40F59755, 0x69CE82D6, 0xA8405D16, 0x31A23B17, 0xF02CE4D7, - 0x63D41011, 0xA25ACFD1, 0x3BB8A9D0, 0xFA367610, 0xD30D6393, 0x1283BC53, 0x8B61DA52, 0x4AEF0592, - 0xF17DBA48, 0x30F36588, 0xA9110389, 0x689FDC49, 0x41A4C9CA, 0x802A160A, 0x19C8700B, 0xD846AFCB, - 0x4BBE5B0D, 0x8A3084CD, 0x13D2E2CC, 0xD25C3D0C, 0xFB67288F, 0x3AE9F74F, 0xA30B914E, 0x62854E8E, - 0x5F8B7E83, 0x9E05A143, 0x07E7C742, 0xC6691882, 0xEF520D01, 0x2EDCD2C1, 0xB73EB4C0, 0x76B06B00, - 0xE5489FC6, 0x24C64006, 0xBD242607, 0x7CAAF9C7, 0x5591EC44, 0x941F3384, 0x0DFD5585, 0xCC738A45, - 0xA1A92C70, 0x6027F3B0, 0xF9C595B1, 0x384B4A71, 0x11705FF2, 0xD0FE8032, 0x491CE633, 0x889239F3, - 0x1B6ACD35, 0xDAE412F5, 0x430674F4, 0x8288AB34, 0xABB3BEB7, 0x6A3D6177, 0xF3DF0776, 0x3251D8B6, - 0x0F5FE8BB, 0xCED1377B, 0x5733517A, 0x96BD8EBA, 0xBF869B39, 0x7E0844F9, 0xE7EA22F8, 0x2664FD38, - 0xB59C09FE, 0x7412D63E, 0xEDF0B03F, 0x2C7E6FFF, 0x05457A7C, 0xC4CBA5BC, 0x5D29C3BD, 0x9CA71C7D, - 0x2735A3A7, 0xE6BB7C67, 0x7F591A66, 0xBED7C5A6, 0x97ECD025, 0x56620FE5, 0xCF8069E4, 0x0E0EB624, - 0x9DF642E2, 0x5C789D22, 0xC59AFB23, 0x041424E3, 0x2D2F3160, 0xECA1EEA0, 0x754388A1, 0xB4CD5761, - 0x89C3676C, 0x484DB8AC, 0xD1AFDEAD, 0x1021016D, 0x391A14EE, 0xF894CB2E, 0x6176AD2F, 0xA0F872EF, - 0x33008629, 0xF28E59E9, 0x6B6C3FE8, 0xAAE2E028, 0x83D9F5AB, 0x42572A6B, 0xDBB54C6A, 0x1A3B93AA, - }, - - { - 0x00000000, 0x9BA54C6F, 0xEC3B9E9F, 0x779ED2F0, 0x03063B7F, 0x98A37710, 0xEF3DA5E0, 0x7498E98F, - 0x060C76FE, 0x9DA93A91, 0xEA37E861, 0x7192A40E, 0x050A4D81, 0x9EAF01EE, 0xE931D31E, 0x72949F71, - 0x0C18EDFC, 0x97BDA193, 0xE0237363, 0x7B863F0C, 0x0F1ED683, 0x94BB9AEC, 0xE325481C, 0x78800473, - 0x0A149B02, 0x91B1D76D, 0xE62F059D, 0x7D8A49F2, 0x0912A07D, 0x92B7EC12, 0xE5293EE2, 0x7E8C728D, - 0x1831DBF8, 0x83949797, 0xF40A4567, 0x6FAF0908, 0x1B37E087, 0x8092ACE8, 0xF70C7E18, 0x6CA93277, - 0x1E3DAD06, 0x8598E169, 0xF2063399, 0x69A37FF6, 0x1D3B9679, 0x869EDA16, 0xF10008E6, 0x6AA54489, - 0x14293604, 0x8F8C7A6B, 0xF812A89B, 0x63B7E4F4, 0x172F0D7B, 0x8C8A4114, 0xFB1493E4, 0x60B1DF8B, - 0x122540FA, 0x89800C95, 0xFE1EDE65, 0x65BB920A, 0x11237B85, 0x8A8637EA, 0xFD18E51A, 0x66BDA975, - 0x3063B7F0, 0xABC6FB9F, 0xDC58296F, 0x47FD6500, 0x33658C8F, 0xA8C0C0E0, 0xDF5E1210, 0x44FB5E7F, - 0x366FC10E, 0xADCA8D61, 0xDA545F91, 0x41F113FE, 0x3569FA71, 0xAECCB61E, 0xD95264EE, 0x42F72881, - 0x3C7B5A0C, 0xA7DE1663, 0xD040C493, 0x4BE588FC, 0x3F7D6173, 0xA4D82D1C, 0xD346FFEC, 0x48E3B383, - 0x3A772CF2, 0xA1D2609D, 0xD64CB26D, 0x4DE9FE02, 0x3971178D, 0xA2D45BE2, 0xD54A8912, 0x4EEFC57D, - 0x28526C08, 0xB3F72067, 0xC469F297, 0x5FCCBEF8, 0x2B545777, 0xB0F11B18, 0xC76FC9E8, 0x5CCA8587, - 0x2E5E1AF6, 0xB5FB5699, 0xC2658469, 0x59C0C806, 0x2D582189, 0xB6FD6DE6, 0xC163BF16, 0x5AC6F379, - 0x244A81F4, 0xBFEFCD9B, 0xC8711F6B, 0x53D45304, 0x274CBA8B, 0xBCE9F6E4, 0xCB772414, 0x50D2687B, - 0x2246F70A, 0xB9E3BB65, 0xCE7D6995, 0x55D825FA, 0x2140CC75, 0xBAE5801A, 0xCD7B52EA, 0x56DE1E85, - 0x60C76FE0, 0xFB62238F, 0x8CFCF17F, 0x1759BD10, 0x63C1549F, 0xF86418F0, 0x8FFACA00, 0x145F866F, - 0x66CB191E, 0xFD6E5571, 0x8AF08781, 0x1155CBEE, 0x65CD2261, 0xFE686E0E, 0x89F6BCFE, 0x1253F091, - 0x6CDF821C, 0xF77ACE73, 0x80E41C83, 0x1B4150EC, 0x6FD9B963, 0xF47CF50C, 0x83E227FC, 0x18476B93, - 0x6AD3F4E2, 0xF176B88D, 0x86E86A7D, 0x1D4D2612, 0x69D5CF9D, 0xF27083F2, 0x85EE5102, 0x1E4B1D6D, - 0x78F6B418, 0xE353F877, 0x94CD2A87, 0x0F6866E8, 0x7BF08F67, 0xE055C308, 0x97CB11F8, 0x0C6E5D97, - 0x7EFAC2E6, 0xE55F8E89, 0x92C15C79, 0x09641016, 0x7DFCF999, 0xE659B5F6, 0x91C76706, 0x0A622B69, - 0x74EE59E4, 0xEF4B158B, 0x98D5C77B, 0x03708B14, 0x77E8629B, 0xEC4D2EF4, 0x9BD3FC04, 0x0076B06B, - 0x72E22F1A, 0xE9476375, 0x9ED9B185, 0x057CFDEA, 0x71E41465, 0xEA41580A, 0x9DDF8AFA, 0x067AC695, - 0x50A4D810, 0xCB01947F, 0xBC9F468F, 0x273A0AE0, 0x53A2E36F, 0xC807AF00, 0xBF997DF0, 0x243C319F, - 0x56A8AEEE, 0xCD0DE281, 0xBA933071, 0x21367C1E, 0x55AE9591, 0xCE0BD9FE, 0xB9950B0E, 0x22304761, - 0x5CBC35EC, 0xC7197983, 0xB087AB73, 0x2B22E71C, 0x5FBA0E93, 0xC41F42FC, 0xB381900C, 0x2824DC63, - 0x5AB04312, 0xC1150F7D, 0xB68BDD8D, 0x2D2E91E2, 0x59B6786D, 0xC2133402, 0xB58DE6F2, 0x2E28AA9D, - 0x489503E8, 0xD3304F87, 0xA4AE9D77, 0x3F0BD118, 0x4B933897, 0xD03674F8, 0xA7A8A608, 0x3C0DEA67, - 0x4E997516, 0xD53C3979, 0xA2A2EB89, 0x3907A7E6, 0x4D9F4E69, 0xD63A0206, 0xA1A4D0F6, 0x3A019C99, - 0x448DEE14, 0xDF28A27B, 0xA8B6708B, 0x33133CE4, 0x478BD56B, 0xDC2E9904, 0xABB04BF4, 0x3015079B, - 0x428198EA, 0xD924D485, 0xAEBA0675, 0x351F4A1A, 0x4187A395, 0xDA22EFFA, 0xADBC3D0A, 0x36197165, - }, - - { - 0x00000000, 0xDD96D985, 0x605CB54B, 0xBDCA6CCE, 0xC0B96A96, 0x1D2FB313, 0xA0E5DFDD, 0x7D730658, - 0x5A03D36D, 0x87950AE8, 0x3A5F6626, 0xE7C9BFA3, 0x9ABAB9FB, 0x472C607E, 0xFAE60CB0, 0x2770D535, - 0xB407A6DA, 0x69917F5F, 0xD45B1391, 0x09CDCA14, 0x74BECC4C, 0xA92815C9, 0x14E27907, 0xC974A082, - 0xEE0475B7, 0x3392AC32, 0x8E58C0FC, 0x53CE1979, 0x2EBD1F21, 0xF32BC6A4, 0x4EE1AA6A, 0x937773EF, - 0xB37E4BF5, 0x6EE89270, 0xD322FEBE, 0x0EB4273B, 0x73C72163, 0xAE51F8E6, 0x139B9428, 0xCE0D4DAD, - 0xE97D9898, 0x34EB411D, 0x89212DD3, 0x54B7F456, 0x29C4F20E, 0xF4522B8B, 0x49984745, 0x940E9EC0, - 0x0779ED2F, 0xDAEF34AA, 0x67255864, 0xBAB381E1, 0xC7C087B9, 0x1A565E3C, 0xA79C32F2, 0x7A0AEB77, - 0x5D7A3E42, 0x80ECE7C7, 0x3D268B09, 0xE0B0528C, 0x9DC354D4, 0x40558D51, 0xFD9FE19F, 0x2009381A, - 0xBD8D91AB, 0x601B482E, 0xDDD124E0, 0x0047FD65, 0x7D34FB3D, 0xA0A222B8, 0x1D684E76, 0xC0FE97F3, - 0xE78E42C6, 0x3A189B43, 0x87D2F78D, 0x5A442E08, 0x27372850, 0xFAA1F1D5, 0x476B9D1B, 0x9AFD449E, - 0x098A3771, 0xD41CEEF4, 0x69D6823A, 0xB4405BBF, 0xC9335DE7, 0x14A58462, 0xA96FE8AC, 0x74F93129, - 0x5389E41C, 0x8E1F3D99, 0x33D55157, 0xEE4388D2, 0x93308E8A, 0x4EA6570F, 0xF36C3BC1, 0x2EFAE244, - 0x0EF3DA5E, 0xD36503DB, 0x6EAF6F15, 0xB339B690, 0xCE4AB0C8, 0x13DC694D, 0xAE160583, 0x7380DC06, - 0x54F00933, 0x8966D0B6, 0x34ACBC78, 0xE93A65FD, 0x944963A5, 0x49DFBA20, 0xF415D6EE, 0x29830F6B, - 0xBAF47C84, 0x6762A501, 0xDAA8C9CF, 0x073E104A, 0x7A4D1612, 0xA7DBCF97, 0x1A11A359, 0xC7877ADC, - 0xE0F7AFE9, 0x3D61766C, 0x80AB1AA2, 0x5D3DC327, 0x204EC57F, 0xFDD81CFA, 0x40127034, 0x9D84A9B1, - 0xA06A2517, 0x7DFCFC92, 0xC036905C, 0x1DA049D9, 0x60D34F81, 0xBD459604, 0x008FFACA, 0xDD19234F, - 0xFA69F67A, 0x27FF2FFF, 0x9A354331, 0x47A39AB4, 0x3AD09CEC, 0xE7464569, 0x5A8C29A7, 0x871AF022, - 0x146D83CD, 0xC9FB5A48, 0x74313686, 0xA9A7EF03, 0xD4D4E95B, 0x094230DE, 0xB4885C10, 0x691E8595, - 0x4E6E50A0, 0x93F88925, 0x2E32E5EB, 0xF3A43C6E, 0x8ED73A36, 0x5341E3B3, 0xEE8B8F7D, 0x331D56F8, - 0x13146EE2, 0xCE82B767, 0x7348DBA9, 0xAEDE022C, 0xD3AD0474, 0x0E3BDDF1, 0xB3F1B13F, 0x6E6768BA, - 0x4917BD8F, 0x9481640A, 0x294B08C4, 0xF4DDD141, 0x89AED719, 0x54380E9C, 0xE9F26252, 0x3464BBD7, - 0xA713C838, 0x7A8511BD, 0xC74F7D73, 0x1AD9A4F6, 0x67AAA2AE, 0xBA3C7B2B, 0x07F617E5, 0xDA60CE60, - 0xFD101B55, 0x2086C2D0, 0x9D4CAE1E, 0x40DA779B, 0x3DA971C3, 0xE03FA846, 0x5DF5C488, 0x80631D0D, - 0x1DE7B4BC, 0xC0716D39, 0x7DBB01F7, 0xA02DD872, 0xDD5EDE2A, 0x00C807AF, 0xBD026B61, 0x6094B2E4, - 0x47E467D1, 0x9A72BE54, 0x27B8D29A, 0xFA2E0B1F, 0x875D0D47, 0x5ACBD4C2, 0xE701B80C, 0x3A976189, - 0xA9E01266, 0x7476CBE3, 0xC9BCA72D, 0x142A7EA8, 0x695978F0, 0xB4CFA175, 0x0905CDBB, 0xD493143E, - 0xF3E3C10B, 0x2E75188E, 0x93BF7440, 0x4E29ADC5, 0x335AAB9D, 0xEECC7218, 0x53061ED6, 0x8E90C753, - 0xAE99FF49, 0x730F26CC, 0xCEC54A02, 0x13539387, 0x6E2095DF, 0xB3B64C5A, 0x0E7C2094, 0xD3EAF911, - 0xF49A2C24, 0x290CF5A1, 0x94C6996F, 0x495040EA, 0x342346B2, 0xE9B59F37, 0x547FF3F9, 0x89E92A7C, - 0x1A9E5993, 0xC7088016, 0x7AC2ECD8, 0xA754355D, 0xDA273305, 0x07B1EA80, 0xBA7B864E, 0x67ED5FCB, - 0x409D8AFE, 0x9D0B537B, 0x20C13FB5, 0xFD57E630, 0x8024E068, 0x5DB239ED, 0xE0785523, 0x3DEE8CA6, - }, - - { - 0x00000000, 0x9D0FE176, 0xE16EC4AD, 0x7C6125DB, 0x19AC8F1B, 0x84A36E6D, 0xF8C24BB6, 0x65CDAAC0, - 0x33591E36, 0xAE56FF40, 0xD237DA9B, 0x4F383BED, 0x2AF5912D, 0xB7FA705B, 0xCB9B5580, 0x5694B4F6, - 0x66B23C6C, 0xFBBDDD1A, 0x87DCF8C1, 0x1AD319B7, 0x7F1EB377, 0xE2115201, 0x9E7077DA, 0x037F96AC, - 0x55EB225A, 0xC8E4C32C, 0xB485E6F7, 0x298A0781, 0x4C47AD41, 0xD1484C37, 0xAD2969EC, 0x3026889A, - 0xCD6478D8, 0x506B99AE, 0x2C0ABC75, 0xB1055D03, 0xD4C8F7C3, 0x49C716B5, 0x35A6336E, 0xA8A9D218, - 0xFE3D66EE, 0x63328798, 0x1F53A243, 0x825C4335, 0xE791E9F5, 0x7A9E0883, 0x06FF2D58, 0x9BF0CC2E, - 0xABD644B4, 0x36D9A5C2, 0x4AB88019, 0xD7B7616F, 0xB27ACBAF, 0x2F752AD9, 0x53140F02, 0xCE1BEE74, - 0x988F5A82, 0x0580BBF4, 0x79E19E2F, 0xE4EE7F59, 0x8123D599, 0x1C2C34EF, 0x604D1134, 0xFD42F042, - 0x41B9F7F1, 0xDCB61687, 0xA0D7335C, 0x3DD8D22A, 0x581578EA, 0xC51A999C, 0xB97BBC47, 0x24745D31, - 0x72E0E9C7, 0xEFEF08B1, 0x938E2D6A, 0x0E81CC1C, 0x6B4C66DC, 0xF64387AA, 0x8A22A271, 0x172D4307, - 0x270BCB9D, 0xBA042AEB, 0xC6650F30, 0x5B6AEE46, 0x3EA74486, 0xA3A8A5F0, 0xDFC9802B, 0x42C6615D, - 0x1452D5AB, 0x895D34DD, 0xF53C1106, 0x6833F070, 0x0DFE5AB0, 0x90F1BBC6, 0xEC909E1D, 0x719F7F6B, - 0x8CDD8F29, 0x11D26E5F, 0x6DB34B84, 0xF0BCAAF2, 0x95710032, 0x087EE144, 0x741FC49F, 0xE91025E9, - 0xBF84911F, 0x228B7069, 0x5EEA55B2, 0xC3E5B4C4, 0xA6281E04, 0x3B27FF72, 0x4746DAA9, 0xDA493BDF, - 0xEA6FB345, 0x77605233, 0x0B0177E8, 0x960E969E, 0xF3C33C5E, 0x6ECCDD28, 0x12ADF8F3, 0x8FA21985, - 0xD936AD73, 0x44394C05, 0x385869DE, 0xA55788A8, 0xC09A2268, 0x5D95C31E, 0x21F4E6C5, 0xBCFB07B3, - 0x8373EFE2, 0x1E7C0E94, 0x621D2B4F, 0xFF12CA39, 0x9ADF60F9, 0x07D0818F, 0x7BB1A454, 0xE6BE4522, - 0xB02AF1D4, 0x2D2510A2, 0x51443579, 0xCC4BD40F, 0xA9867ECF, 0x34899FB9, 0x48E8BA62, 0xD5E75B14, - 0xE5C1D38E, 0x78CE32F8, 0x04AF1723, 0x99A0F655, 0xFC6D5C95, 0x6162BDE3, 0x1D039838, 0x800C794E, - 0xD698CDB8, 0x4B972CCE, 0x37F60915, 0xAAF9E863, 0xCF3442A3, 0x523BA3D5, 0x2E5A860E, 0xB3556778, - 0x4E17973A, 0xD318764C, 0xAF795397, 0x3276B2E1, 0x57BB1821, 0xCAB4F957, 0xB6D5DC8C, 0x2BDA3DFA, - 0x7D4E890C, 0xE041687A, 0x9C204DA1, 0x012FACD7, 0x64E20617, 0xF9EDE761, 0x858CC2BA, 0x188323CC, - 0x28A5AB56, 0xB5AA4A20, 0xC9CB6FFB, 0x54C48E8D, 0x3109244D, 0xAC06C53B, 0xD067E0E0, 0x4D680196, - 0x1BFCB560, 0x86F35416, 0xFA9271CD, 0x679D90BB, 0x02503A7B, 0x9F5FDB0D, 0xE33EFED6, 0x7E311FA0, - 0xC2CA1813, 0x5FC5F965, 0x23A4DCBE, 0xBEAB3DC8, 0xDB669708, 0x4669767E, 0x3A0853A5, 0xA707B2D3, - 0xF1930625, 0x6C9CE753, 0x10FDC288, 0x8DF223FE, 0xE83F893E, 0x75306848, 0x09514D93, 0x945EACE5, - 0xA478247F, 0x3977C509, 0x4516E0D2, 0xD81901A4, 0xBDD4AB64, 0x20DB4A12, 0x5CBA6FC9, 0xC1B58EBF, - 0x97213A49, 0x0A2EDB3F, 0x764FFEE4, 0xEB401F92, 0x8E8DB552, 0x13825424, 0x6FE371FF, 0xF2EC9089, - 0x0FAE60CB, 0x92A181BD, 0xEEC0A466, 0x73CF4510, 0x1602EFD0, 0x8B0D0EA6, 0xF76C2B7D, 0x6A63CA0B, - 0x3CF77EFD, 0xA1F89F8B, 0xDD99BA50, 0x40965B26, 0x255BF1E6, 0xB8541090, 0xC435354B, 0x593AD43D, - 0x691C5CA7, 0xF413BDD1, 0x8872980A, 0x157D797C, 0x70B0D3BC, 0xEDBF32CA, 0x91DE1711, 0x0CD1F667, - 0x5A454291, 0xC74AA3E7, 0xBB2B863C, 0x2624674A, 0x43E9CD8A, 0xDEE62CFC, 0xA2870927, 0x3F88E851, - }, - - { - 0x00000000, 0xB9FBDBE8, 0xA886B191, 0x117D6A79, 0x8A7C6563, 0x3387BE8B, 0x22FAD4F2, 0x9B010F1A, - 0xCF89CC87, 0x7672176F, 0x670F7D16, 0xDEF4A6FE, 0x45F5A9E4, 0xFC0E720C, 0xED731875, 0x5488C39D, - 0x44629F4F, 0xFD9944A7, 0xECE42EDE, 0x551FF536, 0xCE1EFA2C, 0x77E521C4, 0x66984BBD, 0xDF639055, - 0x8BEB53C8, 0x32108820, 0x236DE259, 0x9A9639B1, 0x019736AB, 0xB86CED43, 0xA911873A, 0x10EA5CD2, - 0x88C53E9E, 0x313EE576, 0x20438F0F, 0x99B854E7, 0x02B95BFD, 0xBB428015, 0xAA3FEA6C, 0x13C43184, - 0x474CF219, 0xFEB729F1, 0xEFCA4388, 0x56319860, 0xCD30977A, 0x74CB4C92, 0x65B626EB, 0xDC4DFD03, - 0xCCA7A1D1, 0x755C7A39, 0x64211040, 0xDDDACBA8, 0x46DBC4B2, 0xFF201F5A, 0xEE5D7523, 0x57A6AECB, - 0x032E6D56, 0xBAD5B6BE, 0xABA8DCC7, 0x1253072F, 0x89520835, 0x30A9D3DD, 0x21D4B9A4, 0x982F624C, - 0xCAFB7B7D, 0x7300A095, 0x627DCAEC, 0xDB861104, 0x40871E1E, 0xF97CC5F6, 0xE801AF8F, 0x51FA7467, - 0x0572B7FA, 0xBC896C12, 0xADF4066B, 0x140FDD83, 0x8F0ED299, 0x36F50971, 0x27886308, 0x9E73B8E0, - 0x8E99E432, 0x37623FDA, 0x261F55A3, 0x9FE48E4B, 0x04E58151, 0xBD1E5AB9, 0xAC6330C0, 0x1598EB28, - 0x411028B5, 0xF8EBF35D, 0xE9969924, 0x506D42CC, 0xCB6C4DD6, 0x7297963E, 0x63EAFC47, 0xDA1127AF, - 0x423E45E3, 0xFBC59E0B, 0xEAB8F472, 0x53432F9A, 0xC8422080, 0x71B9FB68, 0x60C49111, 0xD93F4AF9, - 0x8DB78964, 0x344C528C, 0x253138F5, 0x9CCAE31D, 0x07CBEC07, 0xBE3037EF, 0xAF4D5D96, 0x16B6867E, - 0x065CDAAC, 0xBFA70144, 0xAEDA6B3D, 0x1721B0D5, 0x8C20BFCF, 0x35DB6427, 0x24A60E5E, 0x9D5DD5B6, - 0xC9D5162B, 0x702ECDC3, 0x6153A7BA, 0xD8A87C52, 0x43A97348, 0xFA52A8A0, 0xEB2FC2D9, 0x52D41931, - 0x4E87F0BB, 0xF77C2B53, 0xE601412A, 0x5FFA9AC2, 0xC4FB95D8, 0x7D004E30, 0x6C7D2449, 0xD586FFA1, - 0x810E3C3C, 0x38F5E7D4, 0x29888DAD, 0x90735645, 0x0B72595F, 0xB28982B7, 0xA3F4E8CE, 0x1A0F3326, - 0x0AE56FF4, 0xB31EB41C, 0xA263DE65, 0x1B98058D, 0x80990A97, 0x3962D17F, 0x281FBB06, 0x91E460EE, - 0xC56CA373, 0x7C97789B, 0x6DEA12E2, 0xD411C90A, 0x4F10C610, 0xF6EB1DF8, 0xE7967781, 0x5E6DAC69, - 0xC642CE25, 0x7FB915CD, 0x6EC47FB4, 0xD73FA45C, 0x4C3EAB46, 0xF5C570AE, 0xE4B81AD7, 0x5D43C13F, - 0x09CB02A2, 0xB030D94A, 0xA14DB333, 0x18B668DB, 0x83B767C1, 0x3A4CBC29, 0x2B31D650, 0x92CA0DB8, - 0x8220516A, 0x3BDB8A82, 0x2AA6E0FB, 0x935D3B13, 0x085C3409, 0xB1A7EFE1, 0xA0DA8598, 0x19215E70, - 0x4DA99DED, 0xF4524605, 0xE52F2C7C, 0x5CD4F794, 0xC7D5F88E, 0x7E2E2366, 0x6F53491F, 0xD6A892F7, - 0x847C8BC6, 0x3D87502E, 0x2CFA3A57, 0x9501E1BF, 0x0E00EEA5, 0xB7FB354D, 0xA6865F34, 0x1F7D84DC, - 0x4BF54741, 0xF20E9CA9, 0xE373F6D0, 0x5A882D38, 0xC1892222, 0x7872F9CA, 0x690F93B3, 0xD0F4485B, - 0xC01E1489, 0x79E5CF61, 0x6898A518, 0xD1637EF0, 0x4A6271EA, 0xF399AA02, 0xE2E4C07B, 0x5B1F1B93, - 0x0F97D80E, 0xB66C03E6, 0xA711699F, 0x1EEAB277, 0x85EBBD6D, 0x3C106685, 0x2D6D0CFC, 0x9496D714, - 0x0CB9B558, 0xB5426EB0, 0xA43F04C9, 0x1DC4DF21, 0x86C5D03B, 0x3F3E0BD3, 0x2E4361AA, 0x97B8BA42, - 0xC33079DF, 0x7ACBA237, 0x6BB6C84E, 0xD24D13A6, 0x494C1CBC, 0xF0B7C754, 0xE1CAAD2D, 0x583176C5, - 0x48DB2A17, 0xF120F1FF, 0xE05D9B86, 0x59A6406E, 0xC2A74F74, 0x7B5C949C, 0x6A21FEE5, 0xD3DA250D, - 0x8752E690, 0x3EA93D78, 0x2FD45701, 0x962F8CE9, 0x0D2E83F3, 0xB4D5581B, 0xA5A83262, 0x1C53E98A, - }, - - { - 0x00000000, 0xAE689191, 0x87A02563, 0x29C8B4F2, 0xD4314C87, 0x7A59DD16, 0x539169E4, 0xFDF9F875, - 0x73139F4F, 0xDD7B0EDE, 0xF4B3BA2C, 0x5ADB2BBD, 0xA722D3C8, 0x094A4259, 0x2082F6AB, 0x8EEA673A, - 0xE6273E9E, 0x484FAF0F, 0x61871BFD, 0xCFEF8A6C, 0x32167219, 0x9C7EE388, 0xB5B6577A, 0x1BDEC6EB, - 0x9534A1D1, 0x3B5C3040, 0x129484B2, 0xBCFC1523, 0x4105ED56, 0xEF6D7CC7, 0xC6A5C835, 0x68CD59A4, - 0x173F7B7D, 0xB957EAEC, 0x909F5E1E, 0x3EF7CF8F, 0xC30E37FA, 0x6D66A66B, 0x44AE1299, 0xEAC68308, - 0x642CE432, 0xCA4475A3, 0xE38CC151, 0x4DE450C0, 0xB01DA8B5, 0x1E753924, 0x37BD8DD6, 0x99D51C47, - 0xF11845E3, 0x5F70D472, 0x76B86080, 0xD8D0F111, 0x25290964, 0x8B4198F5, 0xA2892C07, 0x0CE1BD96, - 0x820BDAAC, 0x2C634B3D, 0x05ABFFCF, 0xABC36E5E, 0x563A962B, 0xF85207BA, 0xD19AB348, 0x7FF222D9, - 0x2E7EF6FA, 0x8016676B, 0xA9DED399, 0x07B64208, 0xFA4FBA7D, 0x54272BEC, 0x7DEF9F1E, 0xD3870E8F, - 0x5D6D69B5, 0xF305F824, 0xDACD4CD6, 0x74A5DD47, 0x895C2532, 0x2734B4A3, 0x0EFC0051, 0xA09491C0, - 0xC859C864, 0x663159F5, 0x4FF9ED07, 0xE1917C96, 0x1C6884E3, 0xB2001572, 0x9BC8A180, 0x35A03011, - 0xBB4A572B, 0x1522C6BA, 0x3CEA7248, 0x9282E3D9, 0x6F7B1BAC, 0xC1138A3D, 0xE8DB3ECF, 0x46B3AF5E, - 0x39418D87, 0x97291C16, 0xBEE1A8E4, 0x10893975, 0xED70C100, 0x43185091, 0x6AD0E463, 0xC4B875F2, - 0x4A5212C8, 0xE43A8359, 0xCDF237AB, 0x639AA63A, 0x9E635E4F, 0x300BCFDE, 0x19C37B2C, 0xB7ABEABD, - 0xDF66B319, 0x710E2288, 0x58C6967A, 0xF6AE07EB, 0x0B57FF9E, 0xA53F6E0F, 0x8CF7DAFD, 0x229F4B6C, - 0xAC752C56, 0x021DBDC7, 0x2BD50935, 0x85BD98A4, 0x784460D1, 0xD62CF140, 0xFFE445B2, 0x518CD423, - 0x5CFDEDF4, 0xF2957C65, 0xDB5DC897, 0x75355906, 0x88CCA173, 0x26A430E2, 0x0F6C8410, 0xA1041581, - 0x2FEE72BB, 0x8186E32A, 0xA84E57D8, 0x0626C649, 0xFBDF3E3C, 0x55B7AFAD, 0x7C7F1B5F, 0xD2178ACE, - 0xBADAD36A, 0x14B242FB, 0x3D7AF609, 0x93126798, 0x6EEB9FED, 0xC0830E7C, 0xE94BBA8E, 0x47232B1F, - 0xC9C94C25, 0x67A1DDB4, 0x4E696946, 0xE001F8D7, 0x1DF800A2, 0xB3909133, 0x9A5825C1, 0x3430B450, - 0x4BC29689, 0xE5AA0718, 0xCC62B3EA, 0x620A227B, 0x9FF3DA0E, 0x319B4B9F, 0x1853FF6D, 0xB63B6EFC, - 0x38D109C6, 0x96B99857, 0xBF712CA5, 0x1119BD34, 0xECE04541, 0x4288D4D0, 0x6B406022, 0xC528F1B3, - 0xADE5A817, 0x038D3986, 0x2A458D74, 0x842D1CE5, 0x79D4E490, 0xD7BC7501, 0xFE74C1F3, 0x501C5062, - 0xDEF63758, 0x709EA6C9, 0x5956123B, 0xF73E83AA, 0x0AC77BDF, 0xA4AFEA4E, 0x8D675EBC, 0x230FCF2D, - 0x72831B0E, 0xDCEB8A9F, 0xF5233E6D, 0x5B4BAFFC, 0xA6B25789, 0x08DAC618, 0x211272EA, 0x8F7AE37B, - 0x01908441, 0xAFF815D0, 0x8630A122, 0x285830B3, 0xD5A1C8C6, 0x7BC95957, 0x5201EDA5, 0xFC697C34, - 0x94A42590, 0x3ACCB401, 0x130400F3, 0xBD6C9162, 0x40956917, 0xEEFDF886, 0xC7354C74, 0x695DDDE5, - 0xE7B7BADF, 0x49DF2B4E, 0x60179FBC, 0xCE7F0E2D, 0x3386F658, 0x9DEE67C9, 0xB426D33B, 0x1A4E42AA, - 0x65BC6073, 0xCBD4F1E2, 0xE21C4510, 0x4C74D481, 0xB18D2CF4, 0x1FE5BD65, 0x362D0997, 0x98459806, - 0x16AFFF3C, 0xB8C76EAD, 0x910FDA5F, 0x3F674BCE, 0xC29EB3BB, 0x6CF6222A, 0x453E96D8, 0xEB560749, - 0x839B5EED, 0x2DF3CF7C, 0x043B7B8E, 0xAA53EA1F, 0x57AA126A, 0xF9C283FB, 0xD00A3709, 0x7E62A698, - 0xF088C1A2, 0x5EE05033, 0x7728E4C1, 0xD9407550, 0x24B98D25, 0x8AD11CB4, 0xA319A846, 0x0D7139D7, -} -}; - -/// compute CRC32 (bitwise algorithm) -uint32_t crc32_bitwise(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*)data; - int j; - - while(length-- != 0) - { - crc ^= *current++; - for(j = 0; j < 8; j++) - { - // branch-free - crc = (crc >> 1) ^ (-(crc & 1) & Polynomial); - - // branching, much slower: - //if (crc & 1) - // crc = (crc >> 1) ^ Polynomial; - //else - // crc = crc >> 1; - } - } - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (half-byte algoritm) -uint32_t crc32_halfbyte(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*)data; - - /// look-up table for half-byte, same as crc32Lookup[0][16*i] - static const uint32_t Crc32Lookup16[16] = - { - 0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4, 0x4DB26158, 0x5005713C, - 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C, 0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C - }; - - while(length-- != 0) - { - crc = Crc32Lookup16[(crc ^ *current) & 0x0F] ^ (crc >> 4); - crc = Crc32Lookup16[(crc ^ (*current >> 4)) & 0x0F] ^ (crc >> 4); - current++; - } - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (standard algorithm) -uint32_t crc32_1byte(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*)data; - - while(length-- > 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *current++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-4 algorithm) -uint32_t crc32_4bytes(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*)data; - - // process four bytes at once (Slicing-by-4) - while(length >= 4) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - crc = Crc32Lookup[0][one & 0xFF] ^ - Crc32Lookup[1][(one >> 8) & 0xFF] ^ - Crc32Lookup[2][(one >> 16) & 0xFF] ^ - Crc32Lookup[3][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - crc = Crc32Lookup[0][(one >> 24) & 0xFF] ^ - Crc32Lookup[1][(one >> 16) & 0xFF] ^ - Crc32Lookup[2][(one >> 8) & 0xFF] ^ - Crc32Lookup[3][one & 0xFF]; -#endif - - length -= 4; - } - - const uint8_t* currentChar = (const uint8_t*)current; - // remaining 1 to 3 bytes (standard algorithm) - while(length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-8 algorithm) -uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*)data; - - // process eight bytes at once (Slicing-by-8) - while(length >= 8) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - crc = Crc32Lookup[0][two & 0xFF] ^ - Crc32Lookup[1][(two >> 8) & 0xFF] ^ - Crc32Lookup[2][(two >> 16) & 0xFF] ^ - Crc32Lookup[3][(two >> 24) & 0xFF] ^ - Crc32Lookup[4][one & 0xFF] ^ - Crc32Lookup[5][(one >> 8) & 0xFF] ^ - Crc32Lookup[6][(one >> 16) & 0xFF] ^ - Crc32Lookup[7][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - crc = Crc32Lookup[0][(two >> 24) & 0xFF] ^ - Crc32Lookup[1][(two >> 16) & 0xFF] ^ - Crc32Lookup[2][(two >> 8) & 0xFF] ^ - Crc32Lookup[3][two & 0xFF] ^ - Crc32Lookup[4][(one >> 24) & 0xFF] ^ - Crc32Lookup[5][(one >> 16) & 0xFF] ^ - Crc32Lookup[6][(one >> 8) & 0xFF] ^ - Crc32Lookup[7][one & 0xFF]; -#endif - - length -= 8; - } - - const uint8_t* currentChar = (const uint8_t*)current; - // remaining 1 to 7 bytes (standard algorithm) - while(length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times -uint32_t crc32_4x8bytes(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*)data; - - // enabling optimization (at least -O2) automatically unrolls the inner for-loop - const size_t Unroll = 4; - const size_t BytesAtOnce = 8 * Unroll; - size_t unrolling; - // process 4x eight bytes at once (Slicing-by-8) - while(length >= BytesAtOnce) - { - for(unrolling = 0; unrolling < Unroll; unrolling++) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - crc = Crc32Lookup[0][two & 0xFF] ^ - Crc32Lookup[1][(two >> 8) & 0xFF] ^ - Crc32Lookup[2][(two >> 16) & 0xFF] ^ - Crc32Lookup[3][(two >> 24) & 0xFF] ^ - Crc32Lookup[4][one & 0xFF] ^ - Crc32Lookup[5][(one >> 8) & 0xFF] ^ - Crc32Lookup[6][(one >> 16) & 0xFF] ^ - Crc32Lookup[7][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - crc = Crc32Lookup[0][(two >> 24) & 0xFF] ^ - Crc32Lookup[1][(two >> 16) & 0xFF] ^ - Crc32Lookup[2][(two >> 8) & 0xFF] ^ - Crc32Lookup[3][two & 0xFF] ^ - Crc32Lookup[4][(one >> 24) & 0xFF] ^ - Crc32Lookup[5][(one >> 16) & 0xFF] ^ - Crc32Lookup[6][(one >> 8) & 0xFF] ^ - Crc32Lookup[7][one & 0xFF]; -#endif - - } - - length -= BytesAtOnce; - } - - const uint8_t* currentChar = (const uint8_t*)current; - // remaining 1 to 31 bytes (standard algorithm) - while(length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-16 algorithm) -uint32_t crc32_16bytes(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*)data; - - // enabling optimization (at least -O2) automatically unrolls the inner for-loop - const size_t Unroll = 4; - const size_t BytesAtOnce = 16 * Unroll; - size_t unrolling; - - while(length >= BytesAtOnce) - { - for(unrolling = 0; unrolling < Unroll; unrolling++) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[0][four & 0xFF] ^ - Crc32Lookup[1][(four >> 8) & 0xFF] ^ - Crc32Lookup[2][(four >> 16) & 0xFF] ^ - Crc32Lookup[3][(four >> 24) & 0xFF] ^ - Crc32Lookup[4][three & 0xFF] ^ - Crc32Lookup[5][(three >> 8) & 0xFF] ^ - Crc32Lookup[6][(three >> 16) & 0xFF] ^ - Crc32Lookup[7][(three >> 24) & 0xFF] ^ - Crc32Lookup[8][two & 0xFF] ^ - Crc32Lookup[9][(two >> 8) & 0xFF] ^ - Crc32Lookup[10][(two >> 16) & 0xFF] ^ - Crc32Lookup[11][(two >> 24) & 0xFF] ^ - Crc32Lookup[12][one & 0xFF] ^ - Crc32Lookup[13][(one >> 8) & 0xFF] ^ - Crc32Lookup[14][(one >> 16) & 0xFF] ^ - Crc32Lookup[15][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[0][(four >> 24) & 0xFF] ^ - Crc32Lookup[1][(four >> 16) & 0xFF] ^ - Crc32Lookup[2][(four >> 8) & 0xFF] ^ - Crc32Lookup[3][four & 0xFF] ^ - Crc32Lookup[4][(three >> 24) & 0xFF] ^ - Crc32Lookup[5][(three >> 16) & 0xFF] ^ - Crc32Lookup[6][(three >> 8) & 0xFF] ^ - Crc32Lookup[7][three & 0xFF] ^ - Crc32Lookup[8][(two >> 24) & 0xFF] ^ - Crc32Lookup[9][(two >> 16) & 0xFF] ^ - Crc32Lookup[10][(two >> 8) & 0xFF] ^ - Crc32Lookup[11][two & 0xFF] ^ - Crc32Lookup[12][(one >> 24) & 0xFF] ^ - Crc32Lookup[13][(one >> 16) & 0xFF] ^ - Crc32Lookup[14][(one >> 8) & 0xFF] ^ - Crc32Lookup[15][one & 0xFF]; -#endif - } - - length -= BytesAtOnce; - } - - const uint8_t* currentChar = (const uint8_t*)current; - // remaining 1 to 63 bytes (standard algorithm) - while(length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) -uint32_t crc32_16bytes_prefetch(const void* data, size_t length, uint32_t previousCrc32 /*= 0*/, size_t prefetchAhead /*= 256*/) -{ - // CRC code is identical to crc32_16bytes (including unrolling), only added prefetching - // 256 bytes look-ahead seems to be the sweet spot on Core i7 CPUs - - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*)data; - - // enabling optimization (at least -O2) automatically unrolls the for-loop - const size_t Unroll = 4; - const size_t BytesAtOnce = 16 * Unroll; - size_t unrolling; - - while(length >= BytesAtOnce + prefetchAhead) - { - PREFETCH(((const char*)current) + prefetchAhead); - - for(unrolling = 0; unrolling < Unroll; unrolling++) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[0][four & 0xFF] ^ - Crc32Lookup[1][(four >> 8) & 0xFF] ^ - Crc32Lookup[2][(four >> 16) & 0xFF] ^ - Crc32Lookup[3][(four >> 24) & 0xFF] ^ - Crc32Lookup[4][three & 0xFF] ^ - Crc32Lookup[5][(three >> 8) & 0xFF] ^ - Crc32Lookup[6][(three >> 16) & 0xFF] ^ - Crc32Lookup[7][(three >> 24) & 0xFF] ^ - Crc32Lookup[8][two & 0xFF] ^ - Crc32Lookup[9][(two >> 8) & 0xFF] ^ - Crc32Lookup[10][(two >> 16) & 0xFF] ^ - Crc32Lookup[11][(two >> 24) & 0xFF] ^ - Crc32Lookup[12][one & 0xFF] ^ - Crc32Lookup[13][(one >> 8) & 0xFF] ^ - Crc32Lookup[14][(one >> 16) & 0xFF] ^ - Crc32Lookup[15][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[0][(four >> 24) & 0xFF] ^ - Crc32Lookup[1][(four >> 16) & 0xFF] ^ - Crc32Lookup[2][(four >> 8) & 0xFF] ^ - Crc32Lookup[3][four & 0xFF] ^ - Crc32Lookup[4][(three >> 24) & 0xFF] ^ - Crc32Lookup[5][(three >> 16) & 0xFF] ^ - Crc32Lookup[6][(three >> 8) & 0xFF] ^ - Crc32Lookup[7][three & 0xFF] ^ - Crc32Lookup[8][(two >> 24) & 0xFF] ^ - Crc32Lookup[9][(two >> 16) & 0xFF] ^ - Crc32Lookup[10][(two >> 8) & 0xFF] ^ - Crc32Lookup[11][two & 0xFF] ^ - Crc32Lookup[12][(one >> 24) & 0xFF] ^ - Crc32Lookup[13][(one >> 16) & 0xFF] ^ - Crc32Lookup[14][(one >> 8) & 0xFF] ^ - Crc32Lookup[15][one & 0xFF]; -#endif - } - - length -= BytesAtOnce; - } - - const uint8_t* currentChar = (const uint8_t*)current; - // remaining 1 to 63 bytes (standard algorithm) - while(length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - -// Solution to be used on Mac OS X (it gives better preciseness of data compression -// as in case of zlib-cf) -/* -static uint32_t hash_func_default(deflate_state *s, uint32_t UNUSED(h), void* str) { - return crc32_8bytes(str, 32, 0) & s->hash_mask; -} -*/ - -// CRC32 calculation from zlib 1.2.8 - Madler -static uint32_t hash_func_default(deflate_state *s, uint32_t h, void* str) { - return ((h << s->hash_shift) ^ (*(uint32_t*)str)) & s->hash_mask; -} - -#if defined (__aarch64__) - -#pragma GCC push_options -#if __ARM_ARCH >= 8 -#pragma GCC target ("arch=armv8-a+crc") -#endif - -#if defined (__ARM_FEATURE_CRC32) -#include - -static uint32_t hash_func(deflate_state *s, uint32_t UNUSED(h), void* str) { - return __crc32cw(0, *(uint32_t*)str) & s->hash_mask; -} - -#else // ARMv8 without crc32 support - -static uint32_t hash_func(deflate_state *s, uint32_t h, void* str) { - return hash_func_default(s, h, str); -} - -#endif // ARMv8 without crc32 support -#elif defined (__x86_64__) && defined (__linux__) && ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) || (__clang__)) - -static uint32_t hash_func_sse42(deflate_state *s, uint32_t UNUSED(h), void* str) __attribute__ ((__target__ ("sse4.2"))); - -static uint32_t hash_func_sse42(deflate_state *s, uint32_t UNUSED(h), void* str) { - return _mm_crc32_u32(0, *(uint32_t*)str) & s->hash_mask; -} - -static uint32_t hash_func(deflate_state *s, uint32_t UNUSED(h), void* str) __attribute__ ((ifunc ("resolve_hash_func"))); - -void *resolve_hash_func(void) -{ - unsigned int eax, ebx, ecx, edx; - if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) - return hash_func_default; - /* We need SSE4.2 ISA support */ - if (!(ecx & bit_SSE4_2)) - return hash_func_default; - return hash_func_sse42; -} - -#else - -static uint32_t hash_func(deflate_state *s, uint32_t h, void* str) { - return hash_func_default(s, h, str); -} - -#endif - - -/* =========================================================================== - * Insert string str in the dictionary and return the previous head - * of the hash chain (the most recent string with same hash key). - * IN assertion: ACTUAL_MIN_MATCH bytes of str are valid - * (except for the last ACTUAL_MIN_MATCH-1 bytes of the input file). - */ -static Pos insert_string(deflate_state *s, Pos str) { - Pos match_head; - s->ins_h = hash_func(s, s->ins_h, &s->window[str]); - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h]; - s->head[s->ins_h] = (Pos)str; - return match_head; -} - -static void bulk_insert_str(deflate_state *s, Pos startpos, uint32_t count) { - uint32_t idx; - for (idx = 0; idx < count; idx++) { - s->ins_h = hash_func(s, s->ins_h, &s->window[startpos + idx]); - s->prev[(startpos + idx) & s->w_mask] = s->head[s->ins_h]; - s->head[s->ins_h] = (Pos)(startpos + idx); - } -} - -static int _tr_tally_lit(deflate_state *s, uint8_t cc) { - s->d_buf[s->last_lit] = 0; - s->l_buf[s->last_lit++] = cc; - s->dyn_ltree[cc].Freq++; - return (s->last_lit == s->lit_bufsize-1); -} - -static int _tr_tally_dist(deflate_state *s, uint16_t dist, uint8_t len) { - s->d_buf[s->last_lit] = dist; - s->l_buf[s->last_lit++] = len; - dist--; - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - return (s->last_lit == s->lit_bufsize-1); -} -/* =========================================================================== - * Initialize the hash table prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - zmemzero((uint8_t *)s->head, (unsigned)(s->hash_size)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - uint16_t *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - - if (level == Z_DEFAULT_COMPRESSION) level = 6; - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state *)s; - s->strm = strm; - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - - s->window = (uint8_t *) ZALLOC(strm, s->w_size, 2*sizeof(uint8_t)); - s->prev = (Pos *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Pos *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->high_water = 0; /* nothing written to s->window yet */ - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (uint16_t *) ZALLOC(strm, s->lit_bufsize, sizeof(uint16_t)+2); - s->pending_buf = (uint8_t *) overlay; - s->pending_buf_size = (uint64_t)s->lit_bufsize * (sizeof(uint16_t)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(uint16_t); - s->l_buf = s->pending_buf + (1+sizeof(uint16_t))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (uint8_t)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const uint8_t *dictionary; - uint32_t dictLength; -{ - deflate_state *s; - uint32_t str, n; - int wrap; - uint32_t avail; - z_const uint8_t *next; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) - return Z_STREAM_ERROR; - s = strm->state; - wrap = s->wrap; - if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) - return Z_STREAM_ERROR; - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap == 1) - strm->adler = adler32(strm->adler, dictionary, dictLength); - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s->w_size) { - if (wrap == 0) { /* already empty otherwise */ - CLEAR_HASH(s); - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - dictionary += dictLength - s->w_size; /* use the tail */ - dictLength = s->w_size; - } - - /* insert dictionary into window and hash */ - avail = strm->avail_in; - next = strm->next_in; - strm->avail_in = dictLength; - strm->next_in = (z_const uint8_t*)dictionary; - fill_window(s); - while (s->lookahead >= ACTUAL_MIN_MATCH) { - str = s->strstart; - n = s->lookahead - (ACTUAL_MIN_MATCH-1); - bulk_insert_str(s, str, n); - s->strstart = str + n; - s->lookahead = ACTUAL_MIN_MATCH-1; - fill_window(s); - } - s->strstart += s->lookahead; - s->block_start = (long)s->strstart; - s->insert = s->lookahead; - s->lookahead = 0; - s->match_length = s->prev_length = ACTUAL_MIN_MATCH-1; - s->match_available = 0; - strm->next_in = next; - strm->avail_in = avail; - s->wrap = wrap; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateResetKeep (strm) - z_streamp strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (strm) - z_streamp strm; -{ - int ret; - - ret = deflateResetKeep(strm); - if (ret == Z_OK) - lm_init(strm->state); - return ret; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) - z_streamp strm; - gz_headerp head; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePending (strm, pending, bits) - uint32_t *pending; - int *bits; - z_streamp strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (pending != Z_NULL) - *pending = strm->state->pending; - if (bits != Z_NULL) - *bits = strm->state->bi_valid; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) - z_streamp strm; - int bits; - int value; -{ - deflate_state *s; - int put; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - if ((uint8_t *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) - return Z_BUF_ERROR; - do { - put = Buf_size - s->bi_valid; - if (put > bits) - put = bits; - s->bi_buf |= (uint16_t)((value & ((1 << put) - 1)) << s->bi_valid); - s->bi_valid += put; - _tr_flush_bits(s); - value >>= put; - bits -= put; - } while (bits); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - - if (level == Z_DEFAULT_COMPRESSION) level = 6; - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); - if (err == Z_BUF_ERROR && s->pending == 0) - err = Z_OK; - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; - s->nice_match = nice_length; - s->max_chain_length = max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. - */ -uint64_t ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uint64_t sourceLen; -{ - deflate_state *s; - uint64_t complen, wraplen; - uint8_t *str; - - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; - - /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) - return complen + 6; - - /* compute wrapper length */ - s = strm->state; - switch (s->wrap) { - case 0: /* raw deflate */ - wraplen = 0; - break; - case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); - break; - case 2: /* gzip wrapper */ - wraplen = 18; - if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ - if (s->gzhead->extra != Z_NULL) - wraplen += 2 + s->gzhead->extra_len; - str = s->gzhead->name; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - str = s->gzhead->comment; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - if (s->gzhead->hcrc) - wraplen += 2; - } - break; - default: /* for compiler happiness */ - wraplen = 6; - } - - /* if not default parameters, return conservative bound */ - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; - - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13 - 6 + wraplen; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -static void putShortMSB (s, b) - deflate_state *s; - uint32_t b; -{ - put_byte(s, (uint8_t)(b >> 8)); - put_byte(s, (uint8_t)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -static void flush_pending(strm) - z_streamp strm; -{ - uint32_t len; - deflate_state *s = strm->state; - - _tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) { - s->pending_out = s->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the header */ - if (s->status == INIT_STATE) { - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (uint8_t)(s->gzhead->time & 0xff)); - put_byte(s, (uint8_t)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (uint8_t)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (uint8_t)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else - { - uint32_t header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uint32_t level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uint32_t)(strm->adler >> 16)); - putShortMSB(s, (uint32_t)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uint32_t beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uint32_t beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uint32_t beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (uint8_t)(strm->adler & 0xff)); - put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (uint8_t*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - if (s->lookahead == 0) { - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ - if (s->wrap == 2) { - put_byte(s, (uint8_t)(strm->adler & 0xff)); - put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff)); - put_byte(s, (uint8_t)((strm->adler >> 16) & 0xff)); - put_byte(s, (uint8_t)((strm->adler >> 24) & 0xff)); - put_byte(s, (uint8_t)(strm->total_in & 0xff)); - put_byte(s, (uint8_t)((strm->total_in >> 8) & 0xff)); - put_byte(s, (uint8_t)((strm->total_in >> 16) & 0xff)); - put_byte(s, (uint8_t)((strm->total_in >> 24) & 0xff)); - } - else - { - putShortMSB(s, (uint32_t)(strm->adler >> 16)); - putShortMSB(s, (uint32_t)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (strm) - z_streamp strm; -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ - deflate_state *ds; - deflate_state *ss; - uint16_t *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state *) ds; - zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (uint8_t *) ZALLOC(dest, ds->w_size, 2*sizeof(uint8_t)); - ds->prev = (Pos *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Pos *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (uint16_t *) ZALLOC(dest, ds->lit_bufsize, sizeof(uint16_t)+2); - ds->pending_buf = (uint8_t *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(uint8_t)); - zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uint32_t)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(uint16_t); - ds->l_buf = ds->pending_buf + (1+sizeof(uint16_t))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -static int read_buf(strm, buf, size) - z_streamp strm; - uint8_t *buf; - uint32_t size; -{ - uint32_t len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -static void lm_init (s) - deflate_state *s; -{ - s->window_size = (uint64_t)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = ACTUAL_MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -} - -/* longest_match() with minor change to improve performance (in terms of - * execution time). - * - * The pristine longest_match() function is sketched bellow (strip the - * then-clause of the "#ifdef UNALIGNED_OK"-directive) - * - * ------------------------------------------------------------ - * uInt longest_match(...) { - * ... - * do { - * match = s->window + cur_match; //s0 - * if (*(ushf*)(match+best_len-1) != scan_end || //s1 - * *(ushf*)match != scan_start) continue; //s2 - * ... - * - * do { - * } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - * *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - * *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - * *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - * scan < strend); //s3 - * - * ... - * } while(cond); //s4 - * - * ------------------------------------------------------------- - * - * The change include: - * - * 1) The hottest statements of the function is: s0, s1 and s4. Pull them - * together to form a new loop. The benefit is two-fold: - * - * o. Ease the compiler to yield good code layout: the conditional-branch - * corresponding to s1 and its biased target s4 become very close (likely, - * fit in the same cache-line), hence improving instruction-fetching - * efficiency. - * - * o. Ease the compiler to promote "s->window" into register. "s->window" - * is loop-invariant; it is supposed to be promoted into register and keep - * the value throughout the entire loop. However, there are many such - * loop-invariant, and x86-family has small register file; "s->window" is - * likely to be chosen as register-allocation victim such that its value - * is reloaded from memory in every single iteration. By forming a new loop, - * "s->window" is loop-invariant of that newly created tight loop. It is - * lot easier for compiler to promote this quantity to register and keep - * its value throughout the entire small loop. - * - * 2) Transfrom s3 such that it examines sizeof(long)-byte-match at a time. - * This is done by: - * ------------------------------------------------ - * v1 = load from "scan" by sizeof(long) bytes - * v2 = load from "match" by sizeof(lnog) bytes - * v3 = v1 xor v2 - * match-bit = little-endian-machine(yes-for-x86) ? - * count-trailing-zero(v3) : - * count-leading-zero(v3); - * - * match-byte = match-bit/8 - * - * "scan" and "match" advance if necessary - * ------------------------------------------------- - */ - -static uint32_t longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - uint32_t chain_length = s->max_chain_length; /* max hash chain length */ - register uint8_t *scan = s->window + s->strstart; /* current string */ - register uint8_t *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Pos *prev = s->prev; - uint32_t wmask = s->w_mask; - - register uint8_t *strend = s->window + s->strstart + MAX_MATCH; - /* We optimize for a minimal match of four bytes */ - register uint32_t scan_start = *(uint32_t*)scan; - register uint32_t scan_end = *(uint32_t*)(scan+best_len-3); - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uint32_t)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((uint64_t)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - int cont ; - Assert(cur_match < s->strstart, "no future"); - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - cont = 1; - do { - match = s->window + cur_match; - if (likely(*(uint32_t*)(match+best_len-3) != scan_end) || (*(uint32_t*)match != scan_start)) { - if ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0) { - continue; - } else - cont = 0; - } - break; - } while (1); - - if (!cont) - break; - - scan += 4, match+=4; - do { - uint64_t sv = *(uint64_t*)(void*)scan; - uint64_t mv = *(uint64_t*)(void*)match; - uint64_t xor = sv ^ mv; - if (xor) { - int match_byte = __builtin_ctzl(xor) / 8; - scan += match_byte; - match += match_byte; - break; - } else { - scan += 8; - match += 8; - } - } while (scan < strend); - - if (scan > strend) - scan = strend; - - Assert(scan <= s->window+(uint32_t)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; - scan_end = *(uint32_t*)(scan+best_len-3); - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uint32_t)best_len <= s->lookahead) return (uint32_t)best_len; - return s->lookahead; -} - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -static void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -static void fill_window_default(s) - deflate_state *s; -{ - register unsigned n, m; - register Pos *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - s->ins_h = hash_func(s, s->ins_h, &s->window[str + 1]); - while (s->insert) { - s->ins_h = hash_func(s, s->ins_h, &s->window[str + MIN_MATCH-1]); - s->prev[str & s->w_mask] = s->head[s->ins_h]; - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -#if defined (__x86_64__) && defined (__linux__) && ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) || (__clang__)) - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ - -static void fill_window_sse42(deflate_state *) __attribute__ ((__target__ ("sse4.2"))); - -static void fill_window_sse42(s) - deflate_state *s; -{ - register uint32_t n; - uint32_t more; /* Amount of free space at the end of the window. */ - uint32_t wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(uint64_t)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - - if (s->strstart >= wsize+MAX_DIST(s)) { - - unsigned int i; - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; - s->block_start -= (int64_t) wsize; - n = s->hash_size; - __m128i W; - __m128i *q; - W = _mm_set1_epi16(wsize); - q = (__m128i*)s->head; - - for(i = 0; i < n/8; ++i) { - _mm_storeu_si128(q, _mm_subs_epu16(_mm_loadu_si128(q), W)); - q++; - } - - n = wsize; - q = (__m128i*)s->prev; - - for(i = 0; i < n/8; ++i) { - _mm_storeu_si128(q, _mm_subs_epu16(_mm_loadu_si128(q), W)); - q++; - } - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= ACTUAL_MIN_MATCH) { - uint32_t str = s->strstart - s->insert; - uint32_t ins_h = s->window[str]; - while (s->insert) { - ins_h = hash_func(s, ins_h, &s->window[str]); - s->prev[str & s->w_mask] = s->head[ins_h]; - s->head[ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < ACTUAL_MIN_MATCH) - break; - } - s->ins_h = ins_h; - } - /* If the whole input has less than ACTUAL_MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - uint64_t curr = s->strstart + (ulg)(s->lookahead); - uint64_t init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (uint64_t)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (uint64_t)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((uint64_t)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -void *resolve_fill_window(void) -{ - unsigned int eax, ebx, ecx, edx; - if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) - return fill_window_default; - /* We need SSE4.2 ISA support */ - if (!(ecx & bit_SSE4_2)) - return fill_window_default; - return fill_window_sse42; -} - -static void fill_window(deflate_state *) __attribute__ ((ifunc ("resolve_fill_window"))); - -#elif defined (__aarch64__) - -static void fill_window_neon(s) - deflate_state *s; -{ - register uint32_t n; - uint32_t more; /* Amount of free space at the end of the window. */ - uint32_t wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(uint64_t)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - - if (s->strstart >= wsize+MAX_DIST(s)) { - - unsigned int i; - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; - s->block_start -= (int64_t) wsize; - n = s->hash_size; - uint16x8_t W; - uint16_t *q ; - W = vmovq_n_u16(wsize); - q = (uint16_t*)s->head; - - for(i = 0; i < n/8; ++i) { - vst1q_u16(q, vqsubq_u16(vld1q_u16(q), W)); - q+=8; - } - - n = wsize; - q = (uint16_t*)s->prev; - - for(i = 0; i < n/8; ++i) { - vst1q_u16(q, vqsubq_u16(vld1q_u16(q), W)); - q+=8; - } - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= ACTUAL_MIN_MATCH) { - uint32_t str = s->strstart - s->insert; - uint32_t ins_h = s->window[str]; - while (s->insert) { - ins_h = hash_func(s, ins_h, &s->window[str]); - s->prev[str & s->w_mask] = s->head[ins_h]; - s->head[ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < ACTUAL_MIN_MATCH) - break; - } - s->ins_h = ins_h; - } - /* If the whole input has less than ACTUAL_MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - uint64_t curr = s->strstart + (ulg)(s->lookahead); - uint64_t init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (uint64_t)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (uint64_t)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((uint64_t)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -void fill_window(deflate_state *s){ - return fill_window_neon(s); -} - -#else - -void fill_window(deflate_state *s){ - return fill_window_default(s); -} - -#endif - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, last) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (uint8_t *)&s->window[(uint64_t)s->block_start] : \ - (uint8_t *)Z_NULL), \ - (uint64_t)((int64_t)s->strstart - s->block_start), \ - (last)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, last) { \ - FLUSH_BLOCK_ONLY(s, last); \ - if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -static block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - uint64_t max_block_size = 0xffff; - uint64_t max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (int64_t)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (uint64_t)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uint32_t)(s->strstart - max_start); - s->strstart = (uint32_t)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uint32_t)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if ((int64_t)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -static block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus ACTUAL_MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= ACTUAL_MIN_MATCH) { - hash_head = insert_string(s, s->strstart); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < ACTUAL_MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - } - if (s->match_length >= ACTUAL_MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - bflush = _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s->match_length <= s->max_insert_length && - s->lookahead >= ACTUAL_MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - hash_head = insert_string(s, s->strstart); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always ACTUAL_MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else { - s->strstart += s->match_length; - s->match_length = 0; - /* If lookahead < ACTUAL_MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - bflush = _tr_tally_lit (s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < ACTUAL_MIN_MATCH-1 ? s->strstart : ACTUAL_MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -static block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus ACTUAL_MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+3] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= ACTUAL_MIN_MATCH) { - hash_head = insert_string(s, s->strstart); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = ACTUAL_MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED )) { - - /* If prev_match is also ACTUAL_MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = ACTUAL_MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= ACTUAL_MIN_MATCH && s->match_length <= s->prev_length) { - uint32_t mov_fwd ; - uint32_t insert_cnt ; - - uint32_t max_insert = s->strstart + s->lookahead - ACTUAL_MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - bflush = _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - - mov_fwd = s->prev_length - 2; - insert_cnt = mov_fwd; - if (unlikely(insert_cnt > max_insert - s->strstart)) - insert_cnt = max_insert - s->strstart; - - bulk_insert_str(s, s->strstart + 1, insert_cnt); - s->prev_length = 0; - s->match_available = 0; - s->match_length = ACTUAL_MIN_MATCH-1; - s->strstart += mov_fwd + 1; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - bflush = _tr_tally_lit(s, s->window[s->strstart-1]); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - bflush = _tr_tally_lit(s, s->window[s->strstart-1]); - s->match_available = 0; - } - s->insert = s->strstart < ACTUAL_MIN_MATCH-1 ? s->strstart : ACTUAL_MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -static block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - uint32_t prev; /* byte at distance one to match */ - uint8_t *scan, *strend; /* scan goes up to strend for length of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s->match_length = 0; - if (s->lookahead >= ACTUAL_MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); - if (s->match_length > s->lookahead) - s->match_length = s->lookahead; - } - Assert(scan <= s->window+(uint32_t)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of ACTUAL_MIN_MATCH or longer, else emit literal */ - if (s->match_length >= ACTUAL_MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, s->match_length); - - bflush = _tr_tally_dist(s, 1, s->match_length - MIN_MATCH); - - s->lookahead -= s->match_length; - s->strstart += s->match_length; - s->match_length = 0; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - bflush = _tr_tally_lit (s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -static block_state deflate_huff(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s->match_length = 0; - Tracevv((stderr,"%c", s->window[s->strstart])); - bflush = _tr_tally_lit (s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/builtins/zlib/deflate_cf.h b/builtins/zlib/deflate_cf.h deleted file mode 100644 index 696792b3cd660..0000000000000 --- a/builtins/zlib/deflate_cf.h +++ /dev/null @@ -1,333 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define Buf_size 64 -/* size of bit buffer in bi_buf */ - -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - uint16_t freq; /* frequency count */ - uint16_t code; /* bit string */ - } fc; - union { - uint16_t dad; /* father node in Huffman tree */ - uint16_t len; /* length of bit string */ - } dl; -} ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} tree_desc; - -typedef uint16_t Pos; -typedef uint32_t IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - uint8_t *pending_buf; /* output still pending */ - uint64_t pending_buf_size; /* size of pending_buf */ - uint8_t *pending_out; /* next pending byte to output to the stream */ - uint32_t pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - uint32_t gzindex; /* where in extra, name, or comment */ - uint8_t method; /* can only be DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - uint32_t w_size; /* LZ77 window size (32K by default) */ - uint32_t w_bits; /* log2(w_size) (8..16) */ - uint32_t w_mask; /* w_size - 1 */ - - uint8_t *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - uint32_t window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Pos *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Pos *head; /* Heads of the hash chains or NIL. */ - - uint32_t ins_h; /* hash index of string to be inserted */ - uint32_t hash_size; /* number of elements in hash table */ - uint32_t hash_bits; /* log2(hash_size) */ - uint32_t hash_mask; /* hash_size-1 */ - - uint32_t hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uint32_t match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uint32_t strstart; /* start of string to insert */ - uint32_t match_start; /* start of matching string */ - uint32_t lookahead; /* number of valid bytes ahead in window */ - - uint32_t prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uint32_t max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uint32_t max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uint32_t good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - uint16_t bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uint8_t depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uint8_t *l_buf; /* buffer for literals or lengths */ - - uint32_t lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uint32_t last_lit; /* running index in l_buf */ - - uint16_t *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - uint64_t opt_len; /* bit length of current block with optimal trees */ - uint64_t static_len; /* bit length of current block with static trees */ - uint32_t matches; /* number of string matches in current block */ - uint32_t insert; /* bytes at end of window left to insert */ - -#ifdef DEBUG - uint64_t compressed_len; /* total bit length of compressed file mod 2^32 */ - uint64_t bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - uint64_t bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - uint64_t high_water; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - -} deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ - -#define put_short(s, w) { \ - s->pending += 2; \ - *(ush*)(&s->pending_buf[s->pending - 2]) = (w) ; \ -} - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -#define WIN_INIT MAX_MATCH -/* Number of bytes after end of data in window to initialize in order to avoid - memory checker errors from longest match routines */ - - /* in trees.c */ -void ZLIB_INTERNAL _tr_init(deflate_state *s); -int ZLIB_INTERNAL _tr_tally(deflate_state *s, uint32_t dist, unsigned lc); -void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, uint8_t *buf, - uint64_t stored_len, int last); -void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); -void ZLIB_INTERNAL _tr_align(deflate_state *s); -void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, uint8_t *buf, - uint64_t stored_len, int last); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -extern const uint8_t ZLIB_INTERNAL _length_code[]; -extern const uint8_t ZLIB_INTERNAL _dist_code[]; - -#ifdef _MSC_VER - -/* MSC doesn't have __builtin_expect. Just ignore likely/unlikely and - hope the compiler optimizes for the best. -*/ -#define likely(x) (x) -#define unlikely(x) (x) - -int __inline __builtin_ctzl(unsigned long mask) -{ - unsigned long index ; - - return _BitScanForward(&index, mask) == 0 ? 32 : ((int)index) ; -} -#else -#define likely(x) __builtin_expect((x),1) -#define unlikely(x) __builtin_expect((x),0) -#endif - -#endif /* DEFLATE_H */ diff --git a/builtins/zlib/gzclose.c b/builtins/zlib/gzclose.c deleted file mode 100644 index 023d2a650135b..0000000000000 --- a/builtins/zlib/gzclose.c +++ /dev/null @@ -1,24 +0,0 @@ -/* gzclose.c -- zlib gzclose() function - * Copyright (C) 2004, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* gzclose() is in a separate file so that it is linked in only if it is used. - That way the other gzclose functions can be used instead to avoid linking in - unneeded compression or decompression routines. */ -int ZEXPORT gzclose(gzFile file) -{ -#ifndef NO_GZCOMPRESS - gz_statep state; - - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); -#else - return gzclose_r(file); -#endif -} diff --git a/builtins/zlib/gzguts.h b/builtins/zlib/gzguts.h deleted file mode 100644 index d87659d0319fa..0000000000000 --- a/builtins/zlib/gzguts.h +++ /dev/null @@ -1,209 +0,0 @@ -/* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef _LARGEFILE64_SOURCE -# ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE 1 -# endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif -#endif - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include -#include "zlib.h" -#ifdef STDC -# include -# include -# include -#endif -#include - -#ifdef _WIN32 -# include -#endif - -#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) -# include -#endif - -#ifdef WINAPI_FAMILY -# define open _open -# define read _read -# define write _write -# define close _close -#endif - -#ifdef NO_DEFLATE /* for compatibility with old definition */ -# define NO_GZCOMPRESS -#endif - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS -/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 -/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -# ifdef VMS -# define NO_vsnprintf -# endif -# ifdef __OS400__ -# define NO_vsnprintf -# endif -# ifdef __MVS__ -# define NO_vsnprintf -# endif -#endif - -/* unlike snprintf (which is required in C99, yet still not supported by - Microsoft more than a decade later!), _snprintf does not guarantee null - termination of the result -- however this is only used in gzlib.c where - the result is assured to fit in the space provided */ -#ifdef _MSC_VER -# define snprintf _snprintf -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -/* gz* functions always use library allocation functions */ -#ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); -#endif - -/* get errno and strerror definition */ -#if defined UNDER_CE -# include -# define zstrerror() gz_strwinerror((DWORD)GetLastError()) -#else -# ifndef NO_STRERROR -# include -# define zstrerror() strerror(errno) -# else -# define zstrerror() "stdio error (consult errno)" -# endif -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); -#endif - -/* default memLevel */ -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - -/* default i/o buffer size -- double this for output when reading (this and - twice this must be able to fit in an unsigned type) */ -#define GZBUFSIZE 8192 - -/* gzip modes, also provide a little integrity check on the passed structure */ -#define GZ_NONE 0 -#define GZ_READ 7247 -#define GZ_WRITE 31153 -#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ - -/* values for gz_state how */ -#define LOOK 0 /* look for a gzip header */ -#define COPY 1 /* copy input directly */ -#define GZIP 2 /* decompress a gzip stream */ - -/* internal gzip file state data structure */ -typedef struct { - /* exposed contents for gzgetc() macro */ - struct gzFile_s x; /* "x" for exposed */ - /* x.have: number of bytes available at x.next */ - /* x.next: next output data to deliver or write */ - /* x.pos: current position in uncompressed data */ - /* used for both reading and writing */ - int mode; /* see gzip modes above */ - int fd; /* file descriptor */ - char *path; /* path or fd for error messages */ - unsigned size; /* buffer size, zero if not allocated yet */ - unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ - unsigned char *out; /* output buffer (double-sized when reading) */ - int direct; /* 0 if processing gzip, 1 if transparent */ - /* just for reading */ - int how; /* 0: get header, 1: copy, 2: decompress */ - z_off64_t start; /* where the gzip data started, for rewinding */ - int eof; /* true if end of input file reached */ - int past; /* true if read requested past end */ - /* just for writing */ - int level; /* compression level */ - int strategy; /* compression strategy */ - /* seek request */ - z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ - /* error information */ - int err; /* error code */ - char *msg; /* error message */ - /* zlib inflate or deflate stream */ - z_stream strm; /* stream structure in-place (not a pointer) */ -} gz_state; -typedef gz_state FAR *gz_statep; - -/* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); -#if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); -#endif - -/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t - value -- needed when comparing unsigned to z_off64_t, which is signed - (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif diff --git a/builtins/zlib/gzlib.c b/builtins/zlib/gzlib.c deleted file mode 100644 index 71740b60f56fa..0000000000000 --- a/builtins/zlib/gzlib.c +++ /dev/null @@ -1,605 +0,0 @@ -/* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef _WIN32 -#include -#endif - -#include "gzguts.h" - -#if defined(_WIN32) && !defined(__BORLANDC__) -# define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define LSEEK lseek64 -#else -# define LSEEK lseek -#endif -#endif - -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const void *, int, const char *)); - -#if defined UNDER_CE - -/* Map the Windows error number in ERROR to a locale-dependent error message - string and return a pointer to it. Typically, the values for ERROR come - from GetLastError. - - The string pointed to shall not be modified by the application, but may be - overwritten by a subsequent call to gz_strwinerror - - The gz_strwinerror function does not change the current setting of - GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror(DWORD error) -{ - static char buf[1024]; - - wchar_t *msgbuf; - DWORD lasterr = GetLastError(); - DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - error, - 0, /* Default language */ - (LPVOID)&msgbuf, - 0, - NULL); - if (chars != 0) { - /* If there is an \r\n appended, zap it. */ - if (chars >= 2 - && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { - chars -= 2; - msgbuf[chars] = 0; - } - - if (chars > sizeof (buf) - 1) { - chars = sizeof (buf) - 1; - msgbuf[chars] = 0; - } - - wcstombs(buf, msgbuf, chars + 1); - LocalFree(msgbuf); - } - else { - sprintf(buf, "unknown win32 error (%ld)", error); - } - - SetLastError(lasterr); - return buf; -} - -#endif /* UNDER_CE */ - -/* Reset gzip file state */ -local void gz_reset(gz_statep state) -{ - state->x.have = 0; /* no output data available */ - if (state->mode == GZ_READ) { /* for reading ... */ - state->eof = 0; /* not at end of file */ - state->past = 0; /* have not read past end yet */ - state->how = LOOK; /* look for gzip header */ - } - state->seek = 0; /* no seek request pending */ - gz_error(state, Z_OK, NULL); /* clear error */ - state->x.pos = 0; /* no uncompressed data yet */ - state->strm.avail_in = 0; /* no input data yet */ -} - -/* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open(const void *path, int fd, const char *mode) -{ - gz_statep state; - size_t len; - int oflag; -#ifdef O_CLOEXEC - int cloexec = 0; -#endif -#ifdef O_EXCL - int exclusive = 0; -#endif - - /* check input */ - if (path == NULL) - return NULL; - - /* allocate gzFile structure to return */ - state = (gz_statep)malloc(sizeof(gz_state)); - if (state == NULL) - return NULL; - state->size = 0; /* no buffers allocated yet */ - state->want = GZBUFSIZE; /* requested buffer size */ - state->msg = NULL; /* no error message yet */ - - /* interpret mode */ - state->mode = GZ_NONE; - state->level = Z_DEFAULT_COMPRESSION; - state->strategy = Z_DEFAULT_STRATEGY; - state->direct = 0; - while (*mode) { - if (*mode >= '0' && *mode <= '9') - state->level = *mode - '0'; - else - switch (*mode) { - case 'r': - state->mode = GZ_READ; - break; -#ifndef NO_GZCOMPRESS - case 'w': - state->mode = GZ_WRITE; - break; - case 'a': - state->mode = GZ_APPEND; - break; -#endif - case '+': /* can't read and write at the same time */ - free(state); - return NULL; - case 'b': /* ignore -- will request binary anyway */ - break; -#ifdef O_CLOEXEC - case 'e': - cloexec = 1; - break; -#endif -#ifdef O_EXCL - case 'x': - exclusive = 1; - break; -#endif - case 'f': - state->strategy = Z_FILTERED; - break; - case 'h': - state->strategy = Z_HUFFMAN_ONLY; - break; - case 'R': - state->strategy = Z_RLE; - break; - case 'F': - state->strategy = Z_FIXED; - break; - case 'T': - state->direct = 1; - break; - default: /* could consider as an error, but just ignore */ - ; - } - mode++; - } - - /* must provide an "r", "w", or "a" */ - if (state->mode == GZ_NONE) { - free(state); - return NULL; - } - - /* can't force transparent read */ - if (state->mode == GZ_READ) { - if (state->direct) { - free(state); - return NULL; - } - state->direct = 1; /* for empty file */ - } - - /* save the path name for error messages */ -#ifdef _WIN32 - if (fd == -2) { - len = wcstombs(NULL, path, 0); - if (len == (size_t)-1) - len = 0; - } - else -#endif - len = strlen((const char *)path); - state->path = (char *)malloc(len + 1); - if (state->path == NULL) { - free(state); - return NULL; - } -#ifdef _WIN32 - if (fd == -2) - if (len) - wcstombs(state->path, path, len + 1); - else - *(state->path) = 0; - else -#endif -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->path, len + 1, "%s", (const char *)path); -#else - strcpy(state->path, path); -#endif - - /* compute the flags for open() */ - oflag = -#ifdef O_LARGEFILE - O_LARGEFILE | -#endif -#ifdef O_BINARY - O_BINARY | -#endif -#ifdef O_CLOEXEC - (cloexec ? O_CLOEXEC : 0) | -#endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | -#ifdef O_EXCL - (exclusive ? O_EXCL : 0) | -#endif - (state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))); - - /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( -#ifdef _WIN32 - fd == -2 ? _wopen(path, oflag, 0666) : -#endif - open((const char *)path, oflag, 0666)); - if (state->fd == -1) { - free(state->path); - free(state); - return NULL; - } - if (state->mode == GZ_APPEND) - state->mode = GZ_WRITE; /* simplify later checks */ - - /* save the current position for rewinding (only if reading) */ - if (state->mode == GZ_READ) { - state->start = LSEEK(state->fd, 0, SEEK_CUR); - if (state->start == -1) state->start = 0; - } - - /* initialize stream */ - gz_reset(state); - - /* return stream */ - return (gzFile)state; -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(const char *path, const char *mode) -{ - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64(const char *path, const char *mode) -{ - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen(int fd, const char *mode) -{ - char *path; /* identifier for error messages */ - gzFile gz; - - if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) - return NULL; -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ -#else - sprintf(path, "", fd); /* for debugging */ -#endif - gz = gz_open(path, fd, mode); - free(path); - return gz; -} - -/* -- see zlib.h -- */ -#ifdef _WIN32 -gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) -{ - return gz_open(path, -2, mode); -} -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzbuffer(gzFile file, unsigned size) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* make sure we haven't already allocated memory */ - if (state->size != 0) - return -1; - - /* check and set requested size */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ - state->want = size; - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzrewind(gzFile file) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* back up and start over */ - if (LSEEK(state->fd, state->start, SEEK_SET) == -1) - return -1; - gz_reset(state); - return 0; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) -{ - unsigned n; - z_off64_t ret; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* check that there's no error */ - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* can only seek from start or relative to current position */ - if (whence != SEEK_SET && whence != SEEK_CUR) - return -1; - - /* normalize offset to a SEEK_CUR specification */ - if (whence == SEEK_SET) - offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; - - /* if within raw area while reading, just go there */ - if (state->mode == GZ_READ && state->how == COPY && - state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); - if (ret == -1) - return -1; - state->x.have = 0; - state->eof = 0; - state->past = 0; - state->seek = 0; - gz_error(state, Z_OK, NULL); - state->strm.avail_in = 0; - state->x.pos += offset; - return state->x.pos; - } - - /* calculate skip amount, rewinding if needed for back seek when reading */ - if (offset < 0) { - if (state->mode != GZ_READ) /* writing -- can't go backwards */ - return -1; - offset += state->x.pos; - if (offset < 0) /* before start of file! */ - return -1; - if (gzrewind(file) == -1) /* rewind, then skip to offset */ - return -1; - } - - /* if reading, skip what's in output buffer (one less gzgetc() check) */ - if (state->mode == GZ_READ) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? - (unsigned)offset : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - offset -= n; - } - - /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } - return state->x.pos + offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) -{ - z_off64_t ret; - - ret = gzseek64(file, (z_off64_t)offset, whence); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64(gzFile file) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(gzFile file) -{ - z_off64_t ret; - - ret = gztell64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64(gzFile file) -{ - z_off64_t offset; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* compute and return effective offset in file */ - offset = LSEEK(state->fd, 0, SEEK_CUR); - if (offset == -1) - return -1; - if (state->mode == GZ_READ) /* reading */ - offset -= state->strm.avail_in; /* don't count buffered input */ - return offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(gzFile file) -{ - z_off64_t ret; - - ret = gzoffset64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzeof(gzFile file) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return 0; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return 0; - - /* return end-of-file state */ - return state->mode == GZ_READ ? state->past : 0; -} - -/* -- see zlib.h -- */ -const char * ZEXPORT gzerror(gzFile file, int *errnum) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return NULL; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return NULL; - - /* return error information */ - if (errnum != NULL) - *errnum = state->err; - return state->err == Z_MEM_ERROR ? "out of memory" : - (state->msg == NULL ? "" : state->msg); -} - -/* -- see zlib.h -- */ -void ZEXPORT gzclearerr(gzFile file) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return; - - /* clear error and end-of-file */ - if (state->mode == GZ_READ) { - state->eof = 0; - state->past = 0; - } - gz_error(state, Z_OK, NULL); -} - -/* Create an error message in allocated memory and set state->err and - state->msg accordingly. Free any previous error message already there. Do - not try to free or allocate space if the error is Z_MEM_ERROR (out of - memory). Simply save the error message as a static string. If there is an - allocation failure constructing the error message, then convert the error to - out of memory. */ -void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) -{ - /* free previously allocated message and clear */ - if (state->msg != NULL) { - if (state->err != Z_MEM_ERROR) - free(state->msg); - state->msg = NULL; - } - - /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ - if (err != Z_OK && err != Z_BUF_ERROR) - state->x.have = 0; - - /* set error code, and if no message, then done */ - state->err = err; - if (msg == NULL) - return; - - /* for an out of memory error, return literal string when requested */ - if (err == Z_MEM_ERROR) - return; - - /* construct error message with path */ - if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == - NULL) { - state->err = Z_MEM_ERROR; - return; - } -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, - "%s%s%s", state->path, ": ", msg); -#else - strcpy(state->msg, state->path); - strcat(state->msg, ": "); - strcat(state->msg, msg); -#endif - return; -} - -#ifndef INT_MAX -/* portably return maximum value for an int (when limits.h presumed not - available) -- we need to do this to cover cases where 2's complement not - used, since C standard permits 1's complement and sign-bit representations, - otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ - unsigned p, q; - - p = 1; - do { - q = p; - p <<= 1; - p++; - } while (p > q); - return q >> 1; -} -#endif diff --git a/builtins/zlib/gzread.c b/builtins/zlib/gzread.c deleted file mode 100644 index 0fffaea6b2f88..0000000000000 --- a/builtins/zlib/gzread.c +++ /dev/null @@ -1,577 +0,0 @@ -/* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef _WIN32 -#include -#include -#endif - -#include "gzguts.h" - -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_look OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_fetch OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); - -/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from - state->fd, and update state->eof, state->err, and state->msg as appropriate. - This function needs to loop on read(), since read() is not guaranteed to - read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have) -{ - int ret; - - *have = 0; - do { - ret = read(state->fd, buf + *have, len - *have); - if (ret <= 0) - break; - *have += ret; - } while (*have < len); - if (ret < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (ret == 0) - state->eof = 1; - return 0; -} - -/* Load up input buffer and set eof flag if last data loaded -- return -1 on - error, 0 otherwise. Note that the eof flag is set when the end of the input - file is reached, even though there may be unused data in the buffer. Once - that data has been used, no more attempts will be made to read the file. - If strm->avail_in != 0, then the current data is moved to the beginning of - the input buffer, and then the remainder of the buffer is loaded with the - available data from the input file. */ -local int gz_avail(gz_statep state) -{ - unsigned got; - z_streamp strm = &(state->strm); - - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - if (state->eof == 0) { - if (strm->avail_in) { /* copy what's there to the start */ - unsigned char *p = state->in; - unsigned const char *q = strm->next_in; - unsigned n = strm->avail_in; - do { - *p++ = *q++; - } while (--n); - } - if (gz_load(state, state->in + strm->avail_in, - state->size - strm->avail_in, &got) == -1) - return -1; - strm->avail_in += got; - strm->next_in = state->in; - } - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. - If this is the first time in, allocate required memory. state->how will be - left unchanged if there is no more input data available, will be set to COPY - if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression. If direct copying, then leftover input - data from the input buffer will be copied to the output buffer. In that - case, all further file reads will be directly to either the output buffer or - a user buffer. If decompressing, the inflate state will be initialized. - gz_look() will return 0 on success or -1 on failure. */ -local int gz_look(gz_statep state) -{ - z_streamp strm = &(state->strm); - - /* allocate read buffers and inflate memory */ - if (state->size == 0) { - /* allocate buffers */ - state->in = (unsigned char *)malloc(state->want); - state->out = (unsigned char *)malloc(state->want << 1); - if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - state->size = state->want; - - /* allocate inflate memory */ - state->strm.zalloc = Z_NULL; - state->strm.zfree = Z_NULL; - state->strm.opaque = Z_NULL; - state->strm.avail_in = 0; - state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ - free(state->out); - free(state->in); - state->size = 0; - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* get at least the magic bytes in the input buffer */ - if (strm->avail_in < 2) { - if (gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) - return 0; - } - - /* look for gzip magic bytes -- if there, do gzip decoding (note: there is - a logical dilemma here when considering the case of a partially written - gzip file, to wit, if a single 31 byte is written, then we cannot tell - whether this is a single-byte file, or just a partially written gzip - file -- for here we assume that if a gzip file is being written, then - the header will be written in a single operation, so that reading a - single byte is sufficient indication that it is not a gzip file) */ - if (strm->avail_in > 1 && - strm->next_in[0] == 31 && strm->next_in[1] == 139) { - inflateReset(strm); - state->how = GZIP; - state->direct = 0; - return 0; - } - - /* no gzip header -- if we were decoding gzip before, then this is trailing - garbage. Ignore the trailing garbage and finish. */ - if (state->direct == 0) { - strm->avail_in = 0; - state->eof = 1; - state->x.have = 0; - return 0; - } - - /* doing raw i/o, copy any leftover input to output -- this assumes that - the output buffer is larger than the input buffer, which also assures - space for gzungetc() */ - state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } - state->how = COPY; - state->direct = 1; - return 0; -} - -/* Decompress from input to the provided next_out and avail_out in the state. - On return, state->x.have and state->x.next point to the just decompressed - data. If the gzip stream completes, state->how is reset to LOOK to look for - the next gzip stream or raw data, once state->x.have is depleted. Returns 0 - on success, -1 on failure. */ -local int gz_decomp(gz_statep state) -{ - int ret = Z_OK; - unsigned had; - z_streamp strm = &(state->strm); - - /* fill output buffer up to end of deflate stream */ - had = strm->avail_out; - do { - /* get more input for inflate() */ - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) { - gz_error(state, Z_BUF_ERROR, "unexpected end of file"); - break; - } - - /* decompress and handle errors */ - ret = inflate(strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { - gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); - return -1; - } - if (ret == Z_MEM_ERROR) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ - gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); - return -1; - } - } while (strm->avail_out && ret != Z_STREAM_END); - - /* update available output */ - state->x.have = had - strm->avail_out; - state->x.next = strm->next_out - state->x.have; - - /* if the gzip stream completed successfully, look for another */ - if (ret == Z_STREAM_END) - state->how = LOOK; - - /* good decompression */ - return 0; -} - -/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. - Data is either copied from the input file or decompressed from the input - file depending on state->how. If state->how is LOOK, then a gzip header is - looked for to determine whether to copy or decompress. Returns -1 on error, - otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the - end of the input file has been reached and all data has been processed. */ -local int gz_fetch(gz_statep state) -{ - z_streamp strm = &(state->strm); - - do { - switch(state->how) { - case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ - if (gz_look(state) == -1) - return -1; - if (state->how == LOOK) - return 0; - break; - case COPY: /* -> COPY */ - if (gz_load(state, state->out, state->size << 1, &(state->x.have)) - == -1) - return -1; - state->x.next = state->out; - return 0; - case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } - } while (state->x.have == 0 && (!state->eof || strm->avail_in)); - return 0; -} - -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(gz_statep state, z_off64_t len) -{ - unsigned n; - - /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) - /* skip over whatever is in output buffer */ - if (state->x.have) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? - (unsigned)len : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - len -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) - break; - - /* need more data to skip -- load up output buffer */ - else { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - } - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) -{ - unsigned got, n; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return -1; - } - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* get len bytes to buf, or less than len if at the end */ - got = 0; - do { - /* first just try copying data from the output buffer */ - if (state->x.have) { - n = state->x.have > len ? len : state->x.have; - memcpy(buf, state->x.next, n); - state->x.next += n; - state->x.have -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) { - state->past = 1; /* tried to read past end */ - break; - } - - /* need output data -- for small len or new stream load up our output - buffer */ - else if (state->how == LOOK || len < (state->size << 1)) { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - continue; /* no progress yet -- go back to copy above */ - /* the copy above assures that we will leave with space in the - output buffer, allowing at least one gzungetc() to succeed */ - } - - /* large len -- read directly into user buffer */ - else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, len, &n) == -1) - return -1; - } - - /* large len -- decompress directly into user buffer */ - else { /* state->how == GZIP */ - strm->avail_out = len; - strm->next_out = (unsigned char *)buf; - if (gz_decomp(state) == -1) - return -1; - n = state->x.have; - state->x.have = 0; - } - - /* update progress */ - len -= n; - buf = (char *)buf + n; - got += n; - state->x.pos += n; - } while (len); - - /* return number of bytes read into user buffer (will fit in int) */ - return (int)got; -} - -/* -- see zlib.h -- */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -#else -# undef gzgetc -#endif -int ZEXPORT gzgetc(gzFile file) -{ - int ret; - unsigned char buf[1]; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* try output buffer (no need to check for skip request) */ - if (state->x.have) { - state->x.have--; - state->x.pos++; - return *(state->x.next)++; - } - - /* nothing there -- try gzread() */ - ret = gzread(file, buf, 1); - return ret < 1 ? -1 : buf[0]; -} - -int ZEXPORT gzgetc_(gzFile file) -{ - return gzgetc(file); -} - -/* -- see zlib.h -- */ -int ZEXPORT gzungetc(int c, gzFile file) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* can't push EOF */ - if (c < 0) - return -1; - - /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->x.have == 0) { - state->x.have = 1; - state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = c; - state->x.pos--; - state->past = 0; - return c; - } - - /* if no room, give up (must have already done a gzungetc()) */ - if (state->x.have == (state->size << 1)) { - gz_error(state, Z_DATA_ERROR, "out of room to push characters"); - return -1; - } - - /* slide output data if needed and insert byte before existing data */ - if (state->x.next == state->out) { - unsigned char *src = state->out + state->x.have; - unsigned char *dest = state->out + (state->size << 1); - while (src > state->out) - *--dest = *--src; - state->x.next = dest; - } - state->x.have++; - state->x.next--; - state->x.next[0] = c; - state->x.pos--; - state->past = 0; - return c; -} - -/* -- see zlib.h -- */ -char * ZEXPORT gzgets(gzFile file, char *buf, int len) -{ - unsigned left, n; - char *str; - unsigned char *eol; - gz_statep state; - - /* check parameters and get internal structure */ - if (file == NULL || buf == NULL || len < 1) - return NULL; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return NULL; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } - - /* copy output bytes up to new line or len - 1, whichever comes first -- - append a terminating zero to the string (we don't check for a zero in - the contents, let the user worry about that) */ - str = buf; - left = (unsigned)len - 1; - if (left) do { - /* assure that something is in the output buffer */ - if (state->x.have == 0 && gz_fetch(state) == -1) - return NULL; /* error */ - if (state->x.have == 0) { /* end of file */ - state->past = 1; /* read past end */ - break; /* return what we have */ - } - - /* look for end-of-line in current output buffer */ - n = state->x.have > left ? left : state->x.have; - eol = (unsigned char *)memchr(state->x.next, '\n', n); - if (eol != NULL) - n = (unsigned)(eol - state->x.next) + 1; - - /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->x.next, n); - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - left -= n; - buf += n; - } while (left && eol == NULL); - - /* return terminated string, or if nothing, end of file */ - if (buf == str) - return NULL; - buf[0] = 0; - return str; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzdirect(gzFile file) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* if the state is not known, but we can find out, then do so (this is - mainly for right after a gzopen() or gzdopen()) */ - if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) - (void)gz_look(state); - - /* return 1 if transparent, 0 if processing a gzip stream */ - return state->direct; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_r(gzFile file) -{ - int ret, err; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're reading */ - if (state->mode != GZ_READ) - return Z_STREAM_ERROR; - - /* free memory and close file */ - if (state->size) { - inflateEnd(&(state->strm)); - free(state->out); - free(state->in); - } - err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; - gz_error(state, Z_OK, NULL); - free(state->path); - ret = close(state->fd); - free(state); - return ret ? Z_ERRNO : err; -} diff --git a/builtins/zlib/gzwrite.c b/builtins/zlib/gzwrite.c deleted file mode 100644 index dad29e425a11c..0000000000000 --- a/builtins/zlib/gzwrite.c +++ /dev/null @@ -1,564 +0,0 @@ -/* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef _WIN32 -#include -#include -#endif - -#include "gzguts.h" - -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); - -/* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on failure or 0 on success. */ -local int gz_init(gz_statep state) -{ - int ret; - z_streamp strm = &(state->strm); - - /* allocate input buffer */ - state->in = (unsigned char *)malloc(state->want); - if (state->in == NULL) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* only need output buffer and deflate state if compressing */ - if (!state->direct) { - /* allocate output buffer */ - state->out = (unsigned char *)malloc(state->want); - if (state->out == NULL) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); - if (ret != Z_OK) { - free(state->out); - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* mark state as initialized */ - state->size = state->want; - - /* initialize write buffer if compressing */ - if (!state->direct) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = strm->next_out; - } - return 0; -} - -/* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file, otherwise 0. - flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. If gz->direct - is true, then simply write to the output file without compressing, and - ignore flush. */ -local int gz_comp(gz_statep state, int flush) -{ - int ret, got; - unsigned have; - z_streamp strm = &(state->strm); - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return -1; - - /* write directly if requested */ - if (state->direct) { - got = write(state->fd, strm->next_in, strm->avail_in); - if (got < 0 || (unsigned)got != strm->avail_in) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - strm->avail_in = 0; - return 0; - } - - /* run deflate() on provided input until it produces no more output */ - ret = Z_OK; - do { - /* write out current buffer contents if full, or if flushing, but if - doing Z_FINISH then don't write until we get to Z_STREAM_END */ - if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && - (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = write(state->fd, state->x.next, have)) < 0 || - (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (strm->avail_out == 0) { - strm->avail_out = state->size; - strm->next_out = state->out; - } - state->x.next = strm->next_out; - } - - /* compress */ - have = strm->avail_out; - ret = deflate(strm, flush); - if (ret == Z_STREAM_ERROR) { - gz_error(state, Z_STREAM_ERROR, - "internal error: deflate stream corrupt"); - return -1; - } - have -= strm->avail_out; - } while (have); - - /* if that completed a deflate stream, allow another to start */ - if (flush == Z_FINISH) - deflateReset(strm); - - /* all done, no errors */ - return 0; -} - -/* Compress len zeros to output. Return -1 on error, 0 on success. */ -local int gz_zero(gz_statep state, z_off64_t len) -{ - int first; - unsigned n; - z_streamp strm = &(state->strm); - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - - /* compress len zeros (len guaranteed > 0) */ - first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? - (unsigned)len : state->size; - if (first) { - memset(state->in, 0, n); - first = 0; - } - strm->avail_in = n; - strm->next_in = state->in; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - len -= n; - } - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) -{ - unsigned put = len; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* for small len, copy to input buffer, otherwise compress directly */ - if (len < state->size) { - /* copy to input buffer, compress when full */ - do { - unsigned have, copy; - - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - copy = state->size - have; - if (copy > len) - copy = len; - memcpy(state->in + have, buf, copy); - strm->avail_in += copy; - state->x.pos += copy; - buf = (const char *)buf + copy; - len -= copy; - if (len && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } while (len); - } - else { - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* directly compress user buffer to file */ - strm->avail_in = len; - strm->next_in = (z_const Bytef *)buf; - state->x.pos += len; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } - - /* input was all buffered or compressed (put will fit in int) */ - return (int)put; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputc(gzFile file, int c) -{ - unsigned have; - unsigned char buf[1]; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* try writing to input buffer for speed (state->size == 0 if buffer not - initialized) */ - if (state->size) { - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - if (have < state->size) { - state->in[have] = c; - strm->avail_in++; - state->x.pos++; - return c & 0xff; - } - } - - /* no room in buffer or not initialized, use gz_write() */ - buf[0] = c; - if (gzwrite(file, buf, 1) != 1) - return -1; - return c & 0xff; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputs(gzFile file, const char *str) -{ - int ret; - unsigned len; - - /* write string */ - len = (unsigned)strlen(str); - ret = gzwrite(file, str, len); - return ret == 0 && len != 0 ? -1 : ret; -} - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -#include - -/* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) -{ - int size, len; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf((char *)(state->in), format, va); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; -# else - len = vsprintf((char *)(state->in), format, va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf((char *)(state->in), size, format, va); - len = strlen((char *)(state->in)); -# else - len = vsnprintf((char *)(state->in), size, format, va); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) - return 0; - - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; - state->x.pos += len; - return len; -} - -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) -{ - va_list va; - int ret; - - va_start(va, format); - ret = gzvprintf(file, format, va); - va_end(va); - return ret; -} - -#else /* !STDC && !Z_HAVE_STDARG_H */ - -/* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ - int size, len; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that can really pass pointer in ints */ - if (sizeof(int) != sizeof(void *)) - return 0; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; -# else - len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen((char *)(state->in)); -# else - len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, - a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, - a19, a20); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) - return 0; - - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; - state->x.pos += len; - return len; -} - -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzflush(gzFile file, int flush) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* check flush parameter */ - if (flush < 0 || flush > Z_FINISH) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* compress remaining data with requested flush */ - gz_comp(state, flush); - return state->err; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzsetparams(gzFile file, int level, int strategy) -{ - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* if no change is requested, then do nothing */ - if (level == state->level && strategy == state->strategy) - return Z_OK; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* change compression parameters for subsequent input */ - if (state->size) { - /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) - return state->err; - deflateParams(strm, level, strategy); - } - state->level = level; - state->strategy = strategy; - return Z_OK; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_w(gzFile file) -{ - int ret = Z_OK; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're writing */ - if (state->mode != GZ_WRITE) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - ret = state->err; - } - - /* flush, free memory, and close file */ - if (gz_comp(state, Z_FINISH) == -1) - ret = state->err; - if (state->size) { - if (!state->direct) { - (void)deflateEnd(&(state->strm)); - free(state->out); - } - free(state->in); - } - gz_error(state, Z_OK, NULL); - free(state->path); - if (close(state->fd) == -1) - ret = Z_ERRNO; - free(state); - return ret; -} diff --git a/builtins/zlib/infback.c b/builtins/zlib/infback.c deleted file mode 100644 index d7e5360c45758..0000000000000 --- a/builtins/zlib/infback.c +++ /dev/null @@ -1,628 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2011 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size) -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->wnext = 0; - state->whave = 0; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc) -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - state->length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd(z_streamp strm) -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/builtins/zlib/inffast.c b/builtins/zlib/inffast.c deleted file mode 100644 index 282275116695a..0000000000000 --- a/builtins/zlib/inffast.c +++ /dev/null @@ -1,319 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifndef ASMINF - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *in; /* local strm->next_in */ - z_const unsigned char FAR *last; /* have enough input while in < last */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code here; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in; - last = in + (strm->avail_in - 5); - out = strm->next_out; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - here = lcode[hold & lmask]; - dolen: - op = (unsigned)(here.bits); - hold >>= op; - bits -= op; - op = (unsigned)(here.op); - if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - *out++ = (unsigned char)(here.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(here.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - here = dcode[hold & dmask]; - dodist: - op = (unsigned)(here.bits); - hold >>= op; - bits -= op; - op = (unsigned)(here.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - strm->msg = - (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - *out++ = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - *out++ = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - *out++ = *from++; - } while (--len); - continue; - } -#endif - } - from = window; - if (wnext == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = window; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } while (len > 2); - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in; - strm->next_out = out; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and wnext == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/builtins/zlib/inffast.h b/builtins/zlib/inffast.h deleted file mode 100644 index e5c1aa4ca8cd5..0000000000000 --- a/builtins/zlib/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/builtins/zlib/inffixed.h b/builtins/zlib/inffixed.h deleted file mode 100644 index d628327769480..0000000000000 --- a/builtins/zlib/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* WARNING: this file should *not* be used by applications. - It is part of the implementation of this library and is - subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/builtins/zlib/inflate.c b/builtins/zlib/inflate.c deleted file mode 100644 index 224af7e3a64e7..0000000000000 --- a/builtins/zlib/inflate.c +++ /dev/null @@ -1,1473 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common wnext == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, - unsigned copy)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, - unsigned len)); - -int ZEXPORT inflateResetKeep(z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - if (state->wrap) /* to support ill-conceived Java test suite */ - strm->adler = state->wrap & 1; - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - state->sane = 1; - state->back = -1; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflateReset(z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; - return inflateResetKeep(strm); -} - -int ZEXPORT inflateReset2(z_streamp strm, int windowBits) -{ - int wrap; - struct inflate_state FAR *state; - - /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; -#ifdef GUNZIP - if (windowBits < 48) - windowBits &= 15; -#endif - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) - return Z_STREAM_ERROR; - if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { - ZFREE(strm, state->window); - state->window = Z_NULL; - } - - /* update state and reset the rest of it */ - state->wrap = wrap; - state->wbits = (unsigned)windowBits; - return inflateReset(strm); -} - -int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) -{ - int ret; - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->window = Z_NULL; - ret = inflateReset2(strm, windowBits); - if (ret != Z_OK) { - ZFREE(strm, state); - strm->state = Z_NULL; - } - return ret; -} - -int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits < 0) { - state->hold = 0; - state->bits = 0; - return Z_OK; - } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, - state.lencode[low].bits, state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) -{ - struct inflate_state FAR *state; - unsigned dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->wnext = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { - zmemcpy(state->window, end - state->wsize, state->wsize); - state->wnext = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->wnext; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, end - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, end - copy, copy); - state->wnext = copy; - state->whave = state->wsize; - } - else { - state->wnext += dist; - if (state->wnext == state->wsize) state->wnext = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate(z_streamp strm, int flush) -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (state->wbits == 0) - state->wbits = len; - else if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = ZSWAP32(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN_; /* decode codes */ - if (flush == Z_TREES) { - DROPBITS(2); - goto inf_leave; - } - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY_; - if (flush == Z_TREES) goto inf_leave; - case COPY_: - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (const code FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN_; - if (flush == Z_TREES) goto inf_leave; - case LEN_: - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - if (state->mode == TYPE) - state->back = -1; - break; - } - state->back = 0; - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - state->length = (unsigned)here.val; - if ((int)(here.op) == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - state->mode = LIT; - break; - } - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->back = -1; - state->mode = TYPE; - break; - } - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(here.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->was = state->length; - state->mode = DIST; - case DIST: - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - state->extra = (unsigned)(here.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->whave) { - if (state->sane) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - Trace((stderr, "inflate.c too far\n")); - copy -= state->whave; - if (copy > state->length) copy = state->length; - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = 0; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; -#endif - } - if (copy > state->wnext) { - copy -= state->wnext; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->wnext - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if (( -#ifdef GUNZIP - state->flags ? hold : -#endif - ZSWAP32(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (out != strm->avail_out && state->mode < BAD && - (state->mode < CHECK || flush != Z_FINISH))) - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (state->wrap && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0) + - (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd(z_streamp strm) -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength) -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* copy dictionary */ - if (state->whave && dictionary != Z_NULL) { - zmemcpy(dictionary, state->window + state->wnext, - state->whave - state->wnext); - zmemcpy(dictionary + state->whave - state->wnext, - state->window, state->wnext); - } - if (dictLength != Z_NULL) - *dictLength = state->whave; - return Z_OK; -} - -int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) -{ - struct inflate_state FAR *state; - unsigned long dictid; - int ret; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary identifier */ - if (state->mode == DICT) { - dictid = adler32(0L, Z_NULL, 0); - dictid = adler32(dictid, dictionary, dictLength); - if (dictid != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); - if (ret) { - state->mode = MEM; - return Z_MEM_ERROR; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, unsigned len) -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync(z_streamp strm) -{ - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} - -int ZEXPORT inflateUndermine(z_streamp strm, int subvert) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - return Z_OK; -#else - state->sane = 1; - return Z_DATA_ERROR; -#endif -} - -long ZEXPORT inflateMark(z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return ULONG_MAX << 16; - state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + - (state->mode == COPY ? state->length : - (state->mode == MATCH ? state->was - state->length : 0)); -} diff --git a/builtins/zlib/inflate.h b/builtins/zlib/inflate.h deleted file mode 100644 index 95f4986d40022..0000000000000 --- a/builtins/zlib/inflate.h +++ /dev/null @@ -1,122 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY_, /* i/o: same as COPY below, but only first time in */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN_, /* i: same as LEN below, but only first time in */ - LEN, /* i: waiting for length/lit/eob code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to BAD or MEM on error -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) or (raw) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> - HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - (raw) -> TYPEDO - Read deflate blocks: - TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK - STORED -> COPY_ -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN_ - LEN_ -> LEN - Read deflate codes in fixed or dynamic block: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* state maintained between inflate() calls. Approximately 10K bytes. */ -struct inflate_state { - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ - int sane; /* if false, allow invalid distance too far */ - int back; /* bits back of last unprocessed length/lit */ - unsigned was; /* initial length of match */ -}; diff --git a/builtins/zlib/inftrees.c b/builtins/zlib/inftrees.c deleted file mode 100644 index c3f587e34afa2..0000000000000 --- a/builtins/zlib/inftrees.c +++ /dev/null @@ -1,298 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.8.1 Copyright 1995-2013 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits,unsigned short FAR *work) -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code here; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - unsigned match; /* use base and extra for symbol >= match */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 198}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)1; - here.val = (unsigned short)0; - *(*table)++ = here; /* make a table to force an error */ - *(*table)++ = here; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - match = 20; - break; - case LENS: - base = lbase; - extra = lext; - match = 257; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - match = 0; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here.bits = (unsigned char)(len - drop); - if (work[sym] + 1 < match) { - here.op = (unsigned char)0; - here.val = work[sym]; - } - else if (work[sym] >= match) { - here.op = (unsigned char)(extra[work[sym] - match]); - here.val = base[work[sym] - match]; - } - else { - here.op = (unsigned char)(32 + 64); /* end of block */ - here.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = here; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff != 0) { - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - next[huff] = here; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/builtins/zlib/inftrees.h b/builtins/zlib/inftrees.h deleted file mode 100644 index baa53a0b1a199..0000000000000 --- a/builtins/zlib/inftrees.h +++ /dev/null @@ -1,62 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1444, which is the sum of 852 for literal/length codes and 592 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in inflate.c and infback.c. If the root table size is - changed, then these maximum sizes would be need to be recalculated and - updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 592 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/builtins/zlib/trees.c b/builtins/zlib/trees.c deleted file mode 100644 index 645c0fac4fd44..0000000000000 --- a/builtins/zlib/trees.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2012 Jean-loup Gailly - * detect_data_type() function provided freely by Cosmin Truta, 2006 - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef DEBUG -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, const ct_data *ltree, - const ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (ush)value << s->bi_valid; - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= (ush)value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (ush)val << s->bi_valid;\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (ush)(value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG */ - - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ -#ifdef NO_INIT_GLOBAL_POINTERS - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; -#endif - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, - "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void ZLIB_INTERNAL _tr_init(deflate_state *s) -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(deflate_state *s) -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(deflate_state *s, - ct_data *tree, /* the tree to restore */ - int k /* node to move down */ - ) -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(deflate_state *s, tree_desc *desc) /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes ( - ct_data *tree, /* the tree to decorate */ - int max_code, /* largest code with non zero frequency */ - ushf *bl_count) /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree ( - deflate_state *s, - ct_data *tree, /* the tree to be scanned */ - int max_code) /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree ( - deflate_state *s, - ct_data *tree, /* the tree to be scanned */ - int max_code) /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(deflate_state *s) -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees( - deflate_state *s, - int lcodes, int dcodes, int blcodes) /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void ZLIB_INTERNAL _tr_stored_block( - deflate_state *s, - charf *buf, /* input block */ - ulg stored_len, /* length of input block */ - int last) /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) - */ -void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) -{ - bi_flush(s); -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -void ZLIB_INTERNAL _tr_align(deflate_state *s) -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void ZLIB_INTERNAL _tr_flush_block( - deflate_state *s, - charf *buf, /* input block, or NULL if too old */ - ulg stored_len, /* length of input block */ - int last) /* one if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (s->strm->data_type == Z_UNKNOWN) - s->strm->data_type = detect_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (const ct_data *)static_ltree, - (const ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (const ct_data *)s->dyn_ltree, - (const ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int ZLIB_INTERNAL _tr_tally ( - deflate_state *s, - unsigned dist, /* distance of matched string */ - unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block( - deflate_state *s, - const ct_data *ltree, /* literal tree */ - const ct_data *dtree) /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type(deflate_state *s) -{ - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long black_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("white-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse( - unsigned code, /* the value to invert */ - int len) /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(deflate_state *s) -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(deflate_state *s) -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block( - deflate_state *s, - charf *buf, /* the input data */ - unsigned len, /* its length */ - int header) /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/builtins/zlib/trees.h b/builtins/zlib/trees.h deleted file mode 100644 index d35639d82a278..0000000000000 --- a/builtins/zlib/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/builtins/zlib/trees_cf.c b/builtins/zlib/trees_cf.c deleted file mode 100644 index c70d4bbbb16e1..0000000000000 --- a/builtins/zlib/trees_cf.c +++ /dev/null @@ -1,1298 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2012 Jean-loup Gailly - * detect_data_type() function provided freely by Cosmin Truta, 2006 - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate_cf.h" - -#ifdef DEBUG -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -static const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -static const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -static const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -static const uint8_t bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -static ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -static ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uint8_t _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uint8_t _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -static int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -static int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const int *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -static static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -static static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -static static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -static void tr_static_init (void); -static void init_block (deflate_state *s); -static void pqdownheap (deflate_state *s, ct_data *tree, int k); -static void gen_bitlen (deflate_state *s, tree_desc *desc); -static void gen_codes (ct_data *tree, int max_code, uint16_t *bl_count); -static void build_tree (deflate_state *s, tree_desc *desc); -static void scan_tree (deflate_state *s, ct_data *tree, int max_code); -static void send_tree (deflate_state *s, ct_data *tree, int max_code); -static int build_bl_tree (deflate_state *s); -static void send_all_trees (deflate_state *s, int lcodes, int dcodes, - int blcodes); -static void compress_block (deflate_state *s, const ct_data *ltree, - const ct_data *dtree); -static int detect_data_type (deflate_state *s); -static unsigned bi_reverse (unsigned value, int length); -static void bi_windup (deflate_state *s); -static void bi_flush (deflate_state *s); -static void copy_block (deflate_state *s, uint8_t *buf, unsigned len, - int header); - -#ifdef GEN_TREES_H -static void gen_trees_header OF(void); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 64 and value fits in length bits. - */ - - -static void send_bits(deflate_state* s, uint64_t val, int len) { - -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - - s->bi_buf ^= (val<bi_valid); - s->bi_valid += len; - if (s->bi_valid >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = s->bi_buf; - s->pending += 8; - s->bi_valid -= 64; - s->bi_buf = val >> (len - s->bi_valid); - } -} - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -static void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - uint16_t bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ -#ifdef NO_INIT_GLOBAL_POINTERS - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; -#endif - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uint8_t)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "static const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "static const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uint8_t ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, - "const uint8_t ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "static const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "static const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void ZLIB_INTERNAL _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -static void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -static void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -static void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - uint16_t f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (uint16_t)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (uint16_t)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -static void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - uint16_t *bl_count; /* number of codes at each bit length */ -{ - uint16_t next_code[MAX_BITS+1]; /* next code value for each bit length */ - uint16_t code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uint8_t)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (uint16_t)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -static void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (uint16_t)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -static void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -static int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %lld, stat %lld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -static void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %lld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %lld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %lld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) - deflate_state *s; - uint8_t *buf; /* input block */ - uint64_t stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (uint64_t)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) - */ -void ZLIB_INTERNAL _tr_flush_bits(s) - deflate_state *s; -{ - bi_flush(s); -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -void ZLIB_INTERNAL _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) - deflate_state *s; - uint8_t *buf; /* input block, or NULL if too old */ - uint64_t stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ - uint64_t opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (s->strm->data_type == Z_UNKNOWN) - s->strm->data_type = detect_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %lld, stat %lld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %lld, stat %lld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %llu(%llu) stat %llu(%llu) stored %llu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (uint8_t*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != NULL) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != NULL) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (const ct_data *)static_ltree, - (const ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (const ct_data *)s->dyn_ltree, - (const ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - init_block(s); - - if (last) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %llu(%llu) ", s->compressed_len>>3, - s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int ZLIB_INTERNAL _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (uint16_t)dist; - s->l_buf[s->last_lit++] = (uint8_t)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((uint16_t)dist < (ush)MAX_DIST(s) && - (uint16_t)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (uint16_t)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - uint64_t out_length = (ulg)s->last_lit*8L; - uint64_t in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -static void compress_block(s, ltree, dtree) - deflate_state *s; - const ct_data *ltree; /* literal tree */ - const ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - uint64_t bit_buf = s->bi_buf; - int filled = s->bi_valid; - - uint64_t val ; - int len ; - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - uint64_t val = ltree[lc].Code; - int len = ltree[lc].Len; -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - bit_buf ^= (val << filled); - filled += len; - - if(filled >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = bit_buf; - s->pending += 8; - filled -= 64; - bit_buf = val >> (len - filled); - } - - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - uint64_t val ; - int len ; - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - - val = ltree[code+LITERALS+1].Code; - len = ltree[code+LITERALS+1].Len; -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - bit_buf ^= (val << filled); - filled += len; - if(filled >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = bit_buf; - s->pending += 8; - filled -= 64; - bit_buf = val >> (len - filled); - } - - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - val = lc; - len = extra; -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - bit_buf ^= (val << filled); - filled += len; - - if(filled >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = bit_buf; - s->pending += 8; - filled -= 64; - bit_buf = val >> (len - filled); - } - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - val = dtree[code].Code; - len = dtree[code].Len; -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - bit_buf ^= (val << filled); - filled += len; - if(filled >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = bit_buf; - s->pending += 8; - filled -= 64; - bit_buf = val >> (len - filled); - } - - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - - val = dist; - len = extra; - bit_buf ^= (val << filled); - filled += len; -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - if(filled >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = bit_buf; - s->pending += 8; - filled -= 64; - bit_buf = val >> (len - filled); - } - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - val = ltree[END_BLOCK].Code; - len = ltree[END_BLOCK].Len; - -#ifdef DEBUG - Tracevv((stderr," l %2d v %4llx ", len, val)); - Assert(len > 0 && len <= 64, "invalid length"); - s->bits_sent += len; -#endif - bit_buf ^= (val << filled); - filled += len; - - if(filled >= 64) { - *(uint64_t*)(&s->pending_buf[s->pending]) = bit_buf; - s->pending += 8; - filled -= 64; - bit_buf = val >> (len - filled); - } - - s->bi_buf = bit_buf; - s->bi_valid = filled; -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -static int detect_data_type(s) - deflate_state *s; -{ - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long black_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("white-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -static unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -static void bi_flush(s) - deflate_state *s; -{ - while (s->bi_valid >= 16) { - put_short(s, s->bi_buf); - s->bi_buf >>= 16; - s->bi_valid -= 16; - } - if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -static void bi_windup(s) - deflate_state *s; -{ - while (s->bi_valid >= 16) { - put_short(s, s->bi_buf); - s->bi_buf >>= 16; - s->bi_valid -= 16; - } - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -static void copy_block(s, buf, len, header) - deflate_state *s; - uint8_t *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (uint16_t)len); - put_short(s, (uint16_t)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/builtins/zlib/uncompr.c b/builtins/zlib/uncompr.c deleted file mode 100644 index ef963213a54e0..0000000000000 --- a/builtins/zlib/uncompr.c +++ /dev/null @@ -1,55 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ -int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) -{ - z_stream stream; - int err; - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} diff --git a/builtins/zlib/zconf.h b/builtins/zlib/zconf.h deleted file mode 100644 index 9987a775530c0..0000000000000 --- a/builtins/zlib/zconf.h +++ /dev/null @@ -1,511 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/builtins/zlib/zconf_cf.h b/builtins/zlib/zconf_cf.h deleted file mode 100644 index f0cc91bf3b5f4..0000000000000 --- a/builtins/zlib/zconf_cf.h +++ /dev/null @@ -1,511 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H -#include -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef uint8_t Byte; /* 8 bits */ -#endif -typedef uint32_t uInt; /* 32 bits */ -typedef uint64_t uLong; /* 64 bits */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#if HAVE_UNISTD_H /* was set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#if HAVE_STDARG_H /* was set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/builtins/zlib/zlib.h b/builtins/zlib/zlib.h deleted file mode 100644 index 18fd639067f1a..0000000000000 --- a/builtins/zlib/zlib.h +++ /dev/null @@ -1,1772 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 - - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 - (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#ifdef R__HAS_CLOUDFLARE_ZLIB -#include "zconf_cf.h" -#else -#include "zconf.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.8" -#define ZLIB_VERNUM 0x1280 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 8 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - z_const Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total number of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total number of bytes output so far */ - - z_const char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this if - the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers - returned by zalloc for objects of exactly 65536 bytes *must* have their - offset normalized to zero. The default allocation function provided by this - library ensures this (see zutil.c). To reduce memory requirements and avoid - any allocation of 64K objects, at the expense of compression ratio, compile - the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all of the uncompressed data for the - operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not - required to perform an inflation in one step. However it may be used to - inform inflate that a faster approach can be used for the single inflate() - call. Z_FINISH also informs inflate to not maintain a sliding window if the - stream completes, which reduces inflate's memory footprint. If the stream - does not complete, either because not all of the stream is provided or not - enough output space is provided, then a sliding window will be allocated and - inflate() can be called again to continue the operation as if Z_NO_FLUSH had - been used. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The - compressor and decompressor must use exactly the same dictionary (see - inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). deflateSetDictionary does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are Z_NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. The application must insure that the dictionary - that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); -/* - Returns the sliding dictionary being maintained by inflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If inflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. - - inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurrences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible full flush point has been found, - Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point - has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above or -1 << 16 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is potentially more efficient than - inflate() for file i/o applications, in that it avoids copying between the - output and the sliding window by simply making the window itself the output - buffer. inflate() can be faster on modern CPUs when used with large - buffers. inflateBack() trusts the application to not change the output - buffer passed by the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - -#ifndef Z_SOLO - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) 'T' will - request transparent writing or appending with no compression and not using - the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. The addition of - "x" when writing will create the file exclusively, which fails if the file - already exists. On systems that support it, the addition of "e" when - reading or writing will set the flag to close the file on an execve() call. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - -#endif /* !Z_SOLO */ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) - -#ifndef Z_SOLO - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -# define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) -#else -# define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) -#endif - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) -# ifdef Z_PREFIX_SET -# define z_gzopen z_gzopen64 -# define z_gzseek z_gzseek64 -# define z_gztell z_gztell64 -# define z_gzoffset z_gzoffset64 -# define z_adler32_combine z_adler32_combine64 -# define z_crc32_combine z_crc32_combine64 -# else -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# endif -# ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -#else /* Z_SOLO */ - - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - -#endif /* !Z_SOLO */ - -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if defined(_WIN32) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); -# endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/builtins/zlib/zutil.c b/builtins/zlib/zutil.c deleted file mode 100644 index aaeb6da0fc8a9..0000000000000 --- a/builtins/zlib/zutil.c +++ /dev/null @@ -1,309 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" -#ifndef Z_SOLO -# include "gzguts.h" -#endif - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -z_const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch ((int)(sizeof(uInt))) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch ((int)(sizeof(uLong))) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch ((int)(sizeof(voidpf))) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch ((int)(sizeof(z_off_t))) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#ifdef DEBUG - -# ifndef verbose -# define verbose 0 -# endif -int ZLIB_INTERNAL z_verbose = verbose; - -void ZLIB_INTERNAL z_error(char *m) -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(int err) -{ - return ERR_MSG(err); -} - -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; -#endif - -#ifndef HAVE_MEMCPY - -void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#ifndef Z_SOLO - -#ifdef SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} - -#endif /* __TURBOC__ */ - - -#ifdef M_I86 -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) items += size - size; /* make compiler happy */ - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); -} - -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ - -#endif /* !Z_SOLO */ diff --git a/builtins/zlib/zutil.h b/builtins/zlib/zutil.h deleted file mode 100644 index 38906a2b018b0..0000000000000 --- a/builtins/zlib/zutil.h +++ /dev/null @@ -1,229 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include "zlib.h" -#include - -#if defined(STDC) && !defined(Z_SOLO) -# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) -# include -# endif -# include -# include -#endif - -#ifdef Z_SOLO - typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# define OS_CODE 0x00 -# ifndef Z_SOLO -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include -# endif -# else /* MSC or DJGPP */ -# include -# endif -# endif -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -# if defined(M_I86) && !defined(Z_SOLO) -# include -# endif -#endif - -#if defined(MACOS) -# define OS_CODE 0x07 -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f -#endif - -#if defined(__BORLANDC__) && !defined(MSDOS) - #pragma warn -8004 - #pragma warn -8008 - #pragma warn -8066 -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && \ - (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#if defined(pyr) || defined(Z_SOLO) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include - extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -#ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); -#endif - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -/* Reverse the bytes in a 32-bit value */ -#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -#endif /* ZUTIL_H */ diff --git a/builtins/zstd/CMakeLists.txt b/builtins/zstd/CMakeLists.txt index e89a5bef5201a..b2cd2076a7a87 100644 --- a/builtins/zstd/CMakeLists.txt +++ b/builtins/zstd/CMakeLists.txt @@ -25,11 +25,18 @@ if(MSVC) -DCMAKE_CXXFLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_CXXFLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_CXXFLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG}) + if(NOT CMAKE_GENERATOR MATCHES Ninja) + if(winrtdebug) + set(ROOT_ZSTD_BUILD_COMMAND_FLAGS "--config Debug") + else() + set(ROOT_ZSTD_BUILD_COMMAND_FLAGS "--config $,RelWithDebInfo,Release>") + endif() + endif() endif() ExternalProject_Add( BUILTIN_ZSTD - URL https://lcgpackages.web.cern.ch/tarFiles/sources/zstd-${ROOT_ZSTD_VERSION}.tar.gz + URL ${lcgpackages}/zstd-${ROOT_ZSTD_VERSION}.tar.gz URL_HASH SHA256=${ROOT_ZSTD_HASH} PREFIX ${ROOT_ZSTD_PREFIX} SOURCE_SUBDIR "build/cmake" @@ -40,8 +47,8 @@ ExternalProject_Add( -DCMAKE_CXX_VISIBILITY_PRESET=hidden -DCMAKE_C_VISIBILITY_PRESET=hidden -DZSTD_BUILD_SHARED=OFF - BUILD_COMMAND ${CMAKE_COMMAND} --build "/" --config $ - INSTALL_COMMAND ${CMAKE_COMMAND} --install "/" --config $ + BUILD_COMMAND ${CMAKE_COMMAND} --build "/" ${ROOT_ZSTD_BUILD_COMMAND_FLAGS} + INSTALL_COMMAND ${CMAKE_COMMAND} --install "/" ${ROOT_ZSTD_BUILD_COMMAND_FLAGS} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 BUILD_IN_SOURCE 1 BUILD_BYPRODUCTS ${ROOT_ZSTD_LIBRARY} @@ -55,3 +62,10 @@ set_target_properties(ZSTD::ZSTD PROPERTIES IMPORTED_LOCATION ${ROOT_ZSTD_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES ${ZSTD_INCLUDE_DIR} ) + +# Set the canonical output of find_package according to +# https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names +set(ZSTD_INCLUDE_DIRS ${ZSTD_INCLUDE_DIR} PARENT_SCOPE) +set(ZSTD_LIBRARIES ${ROOT_ZSTD_LIBRARY} PARENT_SCOPE) +set(ZSTD_FOUND TRUE PARENT_SCOPE) +set(ZSTD_VERSION ${ROOT_ZSTD_VERSION} PARENT_SCOPE) diff --git a/cmake/modules/CheckCompiler.cmake b/cmake/modules/CheckCompiler.cmake index 806be1c9a1ef2..62e9f0ce9c402 100644 --- a/cmake/modules/CheckCompiler.cmake +++ b/cmake/modules/CheckCompiler.cmake @@ -70,19 +70,9 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") string(REGEX REPLACE "^.*[ ]version[ ][0-9]+\\.([0-9]+).*" "\\1" CLANG_MINOR "${_clang_version_info}") if(CMAKE_GENERATOR STREQUAL "Ninja") - # LLVM/Clang are automatically checking if we are in interactive terminal mode. - # We use color output only for Ninja, because Ninja by default is buffering the output, - # so Clang disables colors as it is sure whether the output goes to a file or to a terminal. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcolor-diagnostics") - endif() - if(ccache AND CCACHE_VERSION VERSION_LESS "3.2.0") - # https://bugzilla.samba.org/show_bug.cgi?id=8118 - # Call to 'ccache clang' is triggering next warning (valid for ccache 3.1.x, fixed in 3.2): - # "clang: warning: argument unused during compilation: '-c" - # Adding -Qunused-arguments provides a workaround for the bug. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments") + # Since Ninja buffers outputs, the builtin tty colour detection fails + # https://github.com/ninja-build/ninja/wiki/FAQ#why-does-my-program-with-colored-output-not-have-color-under-ninja + set(CMAKE_COLOR_DIAGNOSTICS ON) endif() else() set(CLANG_MAJOR 0) diff --git a/cmake/modules/Findgl2ps.cmake b/cmake/modules/Findgl2ps.cmake index cfbd1172635b0..7efaf98d46f01 100644 --- a/cmake/modules/Findgl2ps.cmake +++ b/cmake/modules/Findgl2ps.cmake @@ -7,23 +7,32 @@ # - Locate gl2ps library # Defines: # -# GL2PS_FOUND -# GL2PS_INCLUDE_DIR -# GL2PS_INCLUDE_DIRS (not cached) -# GL2PS_LIBRARIES +# gl2ps_FOUND +# gl2ps_INCLUDE_DIR +# gl2ps_INCLUDE_DIRS (not cached) +# gl2ps_LIBRARIES -find_path(GL2PS_INCLUDE_DIR NAMES gl2ps.h HINTS ${GL2PS_DIR}/include $ENV{GL2PS_DIR}/include /usr/include) -find_library(GL2PS_LIBRARY NAMES gl2ps HINTS ${GL2PS_DIR}/lib $ENV{GL2PS_DIR}/lib) +find_path(gl2ps_INCLUDE_DIR NAMES gl2ps.h HINTS ${gl2ps_DIR}/include $ENV{gl2ps_DIR}/include /usr/include) +find_library(gl2ps_LIBRARY NAMES gl2ps HINTS ${gl2ps_DIR}/lib $ENV{gl2ps_DIR}/lib) -set(GL2PS_INCLUDE_DIRS ${GL2PS_INCLUDE_DIR}) -if(GL2PS_LIBRARY) - set(GL2PS_LIBRARIES ${GL2PS_LIBRARY}) +set(gl2ps_INCLUDE_DIRS ${gl2ps_INCLUDE_DIR}) +if(gl2ps_LIBRARY) + set(gl2ps_LIBRARIES ${gl2ps_LIBRARY}) endif() -# handle the QUIETLY and REQUIRED arguments and set GL2PS_FOUND to TRUE if +# handle the QUIETLY and REQUIRED arguments and set gl2ps_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(gl2ps DEFAULT_MSG GL2PS_LIBRARY GL2PS_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(gl2ps DEFAULT_MSG gl2ps_LIBRARY gl2ps_INCLUDE_DIR) -mark_as_advanced(GL2PS_FOUND GL2PS_INCLUDE_DIR GL2PS_LIBRARY) +mark_as_advanced(gl2ps_FOUND gl2ps_INCLUDE_DIR gl2ps_LIBRARY) + +if(gl2ps_FOUND) + if(NOT TARGET gl2ps::g2ps) + add_library(gl2ps::gl2ps UNKNOWN IMPORTED) + set_target_properties(gl2ps::gl2ps PROPERTIES + IMPORTED_LOCATION "${gl2ps_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${gl2ps_INCLUDE_DIR}") + endif() +endif() diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index 669c4c401bd96..51fbd42163432 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -202,16 +202,6 @@ if(all AND minimal) message(FATAL_ERROR "The 'all' and 'minimal' options are mutually exclusive") endif() -#--- Compression algorithms in ROOT------------------------------------------------------------- -set(compression_default "zlib" CACHE STRING "Default compression algorithm (zlib (default), lz4, zstd or lzma)") -string(TOLOWER "${compression_default}" compression_default) -if("${compression_default}" MATCHES "zlib|lz4|lzma|zstd") - message(STATUS "ROOT default compression algorithm: ${compression_default}") -else() - message(FATAL_ERROR "Unsupported compression algorithm: ${compression_default}\n" - "Known values are zlib, lzma, lz4, zstd (case-insensitive).") -endif() - #--- The 'all' option switches ON major options--------------------------------------------------- if(all) set(arrow_defvalue ON) @@ -381,8 +371,9 @@ endif() #---Removed options------------------------------------------------------------ # Please notify SPI when adding to this list -foreach(opt afdsmgrd afs alien bonjour builtin_afterimage builtin_davix castor chirp cxx11 cxx14 cxx17 - cxxmodules exceptions geocad gfal glite globus gsl_shared hdfs html ios jemalloc krb5 +foreach(opt afdsmgrd afs alien bonjour builtin_afterimage builtin_davix castor chirp + compression_default cxx11 cxx14 cxx17 cxxmodules exceptions + geocad gfal glite globus gsl_shared hdfs html ios jemalloc krb5 ldap memstat minuit2 monalisa oracle proof pyroot-python2 pyroot_legacy pythia6 pythia6_nolink python qt qtgsi qt5web rfio ruby sapdb srp table tcmalloc vmc xproofd mysql odbc pgsql) diff --git a/cmake/modules/RootConfiguration.cmake b/cmake/modules/RootConfiguration.cmake index d223c74be3754..97445596e7ace 100644 --- a/cmake/modules/RootConfiguration.cmake +++ b/cmake/modules/RootConfiguration.cmake @@ -396,18 +396,10 @@ else() set(hasroot7 undef) endif() -set(uselz4 undef) -set(usezlib undef) -set(uselzma undef) -set(usezstd undef) -set(use${compression_default} define) - -# cloudflare zlib is available only on x86 and aarch64 platforms with Linux -# for other platforms we have available builtin zlib 1.2.8 -if(builtin_zlib AND ZLIB_CF) - set(usecloudflarezlib define) -else() - set(usecloudflarezlib undef) +if(ZLIB_NG) + set(usezlibng define) +else() + set(usezlibng undef) endif() if(runtime_cxxmodules) set(usecxxmodules define) diff --git a/cmake/modules/RootMacros.cmake b/cmake/modules/RootMacros.cmake index 6b0a0702a6826..9e1dfce102fef 100644 --- a/cmake/modules/RootMacros.cmake +++ b/cmake/modules/RootMacros.cmake @@ -34,13 +34,21 @@ else() set(runtimedir ${CMAKE_INSTALL_PYTHONDIR}) endif() -if(CMAKE_GENERATOR MATCHES Ninja OR CMAKE_GENERATOR MATCHES "Visual Studio") +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set(GeneratorNeedsResourecLock False) set(GeneratorNeedsBuildSerialization True) - if(MSVC) - set(build_config "--config $") + if(winrtdebug) + set(build_config "--config Debug") + else() + set(build_config "--config $,RelWithDebInfo,Release>") endif() endif() +if(CMAKE_GENERATOR MATCHES Ninja) + set(GeneratorNeedsResourecLock True) + set(GeneratorNeedsBuildSerialization True) +endif() + set(ROOT_LIBRARY_PROPERTIES_NO_VERSION ${ROOT_LIBRARY_PROPERTIES_NO_VERSION} SUFFIX ${libsuffix} PREFIX ${libprefix} ) @@ -1316,7 +1324,7 @@ endmacro() # and then use those for linking. # LIBRARIES lib1 lib2 : private arguments for target_link_library() # DEPENDENCIES lib1 lib2 : PUBLIC arguments for target_link_library() such as Core, MathCore -# BUILTINS builtin1 builtin2 : builtins like AFTERIMAGE +# BUILTINS builtin1 builtin2 : builtins like xxhash # LINKDEF LinkDef.h : linkdef file, default value is "LinkDef.h" # DICTIONARY_OPTIONS option : options passed to rootcling # INSTALL_OPTIONS option : options passed to install headers @@ -2258,10 +2266,19 @@ endfunction() # # Arguments: # target - The CMake target (e.g., a shared library or executable) -# install_dir - The install subdirectory relative to CMAKE_INSTALL_PREFIX +# install_dir - The install subdirectory relative to CMAKE_INSTALL_PREFIX, +# or an absolute directory. #---------------------------------------------------------------------------- function(ROOT_APPEND_LIBDIR_TO_INSTALL_RPATH target install_dir) - cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR BASE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${install_dir}" OUTPUT_VARIABLE to_libdir) + + # Check if install_dir is absolute + if(IS_ABSOLUTE "${install_dir}") + set(base_dir "${install_dir}") + else() + set(base_dir "${CMAKE_INSTALL_PREFIX}/${install_dir}") + endif() + + cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR BASE_DIRECTORY "${base_dir}" OUTPUT_VARIABLE to_libdir) # New path if(APPLE) @@ -2514,7 +2531,7 @@ endfunction(ROOTTEST_ADD_AUTOMACROS) # order to manage dependencies. # #------------------------------------------------------------------------------- -macro(ROOTTEST_COMPILE_MACRO filename) +function(ROOTTEST_COMPILE_MACRO filename) CMAKE_PARSE_ARGUMENTS(ARG "" "BUILDOBJ;BUILDLIB" "FIXTURES_SETUP;FIXTURES_CLEANUP;FIXTURES_REQUIRED" ${ARGN}) # Add defines to root_compile_macro, in order to have out-of-source builds @@ -2555,6 +2572,7 @@ macro(ROOTTEST_COMPILE_MACRO filename) ROOTTEST_TARGETNAME_FROM_FILE(COMPILE_MACRO_TEST ${filename}) set(COMPILE_MACRO_TEST ${COMPILE_MACRO_TEST}-build) + set(COMPILE_MACRO_TEST ${COMPILE_MACRO_TEST} PARENT_SCOPE) add_test(NAME ${COMPILE_MACRO_TEST} COMMAND ${compile_macro_command}) if(NOT MSVC OR win_broken_tests) @@ -2575,7 +2593,7 @@ macro(ROOTTEST_COMPILE_MACRO filename) FIXTURES_REQUIRED ${ARG_FIXTURES_REQUIRED}) endif() -endmacro(ROOTTEST_COMPILE_MACRO) +endfunction(ROOTTEST_COMPILE_MACRO) #------------------------------------------------------------------------------- # @@ -2665,7 +2683,9 @@ macro(ROOTTEST_GENERATE_DICTIONARY dictname) set_property(TEST ${GENERATE_DICTIONARY_TEST} PROPERTY ENVIRONMENT ${ROOTTEST_ENVIRONMENT}) if(GeneratorNeedsBuildSerialization) - set_property(TEST ${GENERATE_DICTIONARY_TEST} APPEND PROPERTY RESOURCE_LOCK CMAKE_BUILD) + if(GeneratorNeedsResourecLock) + set_property(TEST ${GENERATE_DICTIONARY_TEST} APPEND PROPERTY RESOURCE_LOCK CMAKE_BUILD) + endif() set_property(TEST ${GENERATE_DICTIONARY_TEST} APPEND PROPERTY FIXTURES_REQUIRED CMAKE_BUILD_ALL) endif() @@ -2773,14 +2793,17 @@ macro(ROOTTEST_GENERATE_REFLEX_DICTIONARY dictionary) set_property(TEST ${GENERATE_REFLEX_TEST} PROPERTY ENVIRONMENT ${ROOTTEST_ENVIRONMENT}) if(GeneratorNeedsBuildSerialization) - set_property(TEST ${GENERATE_REFLEX_TEST} APPEND PROPERTY RESOURCE_LOCK CMAKE_BUILD) + if(GeneratorNeedsResourecLock) + set_property(TEST ${GENERATE_REFLEX_TEST} APPEND PROPERTY RESOURCE_LOCK CMAKE_BUILD) + endif() set_property(TEST ${GENERATE_REFLEX_TEST} APPEND PROPERTY FIXTURES_REQUIRED CMAKE_BUILD_ALL) endif() if (ARG_FIXTURES_SETUP) - set_property(TEST ${GENERATE_REFLEX_TEST} PROPERTY - FIXTURES_SETUP ${ARG_FIXTURES_SETUP}) + set(more_fixtures ${ARG_FIXTURES_SETUP}) endif() + set_property(TEST ${GENERATE_REFLEX_TEST} PROPERTY + FIXTURES_SETUP ${GENERATE_REFLEX_TEST}-fixture ${more_fixtures}) if (ARG_FIXTURES_CLEANUP) set_property(TEST ${GENERATE_REFLEX_TEST} PROPERTY @@ -2885,7 +2908,9 @@ macro(ROOTTEST_GENERATE_EXECUTABLE executable) endif() if(GeneratorNeedsBuildSerialization) - set_property(TEST ${GENERATE_EXECUTABLE_TEST} APPEND PROPERTY RESOURCE_LOCK CMAKE_BUILD) + if(GeneratorNeedsResourecLock) + set_property(TEST ${GENERATE_EXECUTABLE_TEST} APPEND PROPERTY RESOURCE_LOCK CMAKE_BUILD) + endif() set_property(TEST ${GENERATE_EXECUTABLE_TEST} APPEND PROPERTY FIXTURES_REQUIRED CMAKE_BUILD_ALL) endif() @@ -3241,7 +3266,7 @@ function(ROOTTEST_ADD_TEST testname) if(ARG_DEPENDS) foreach(dep ${ARG_DEPENDS}) if(${dep} MATCHES "[.]C" OR ${dep} MATCHES "[.]cxx" OR ${dep} MATCHES "[.]h") - ROOTTEST_COMPILE_MACRO(${dep}) + ROOTTEST_COMPILE_MACRO(${dep} FIXTURES_SETUP compile-macro-${dep}-fixture) list(APPEND deplist ${COMPILE_MACRO_TEST}) elseif(NOT ${dep} MATCHES "^roottest-") list(APPEND deplist ${testprefix}-${dep}) @@ -3249,6 +3274,16 @@ function(ROOTTEST_ADD_TEST testname) list(APPEND deplist ${dep}) endif() endforeach() + # Now extract all fixtures from the dependencies, so the fixture-providing + # tests get started even if using --rerun-failed, or -R or similar + foreach(dep ${deplist}) + if(TEST ${dep}) + get_test_property(${dep} FIXTURES_SETUP test_fixtures) + if(NOT test_fixtures STREQUAL "NOTFOUND") + list(APPEND fixtures_from_depends_argument ${test_fixtures}) + endif() + endif() + endforeach() endif(ARG_DEPENDS) if(ARG_FAILREGEX) @@ -3316,6 +3351,7 @@ function(ROOTTEST_ADD_TEST testname) if (ARG_FIXTURES_REQUIRED) set(fixtures_required ${ARG_FIXTURES_REQUIRED}) endif() + list(APPEND fixtures_required ${fixtures_from_depends_argument}) if (ARG_RESOURCE_LOCK) set(resource_lock ${ARG_RESOURCE_LOCK}) diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 30a94d1858073..220f331595e3e 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -78,7 +78,7 @@ include(CheckIncludeFileCXX) include(ExternalProject) include(FindPackageHandleStandardArgs) -set(lcgpackages http://lcgpackages.web.cern.ch/lcgpackages/tarFiles/sources) +set(lcgpackages https://lcgpackages.web.cern.ch/lcgpackages/tarFiles/sources) string(REPLACE "-Werror " "" ROOT_EXTERNAL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ") #--- Search for packages that are absolutely necessary-------------------------- @@ -108,10 +108,20 @@ foreach(suffix FOUND INCLUDE_DIR LIBRARY LIBRARY_DEBUG LIBRARY_RELEASE LIBRARIES unset(ZSTD_${suffix} CACHE) endforeach() -ROOT_FIND_REQUIRED_DEP(ZLIB builtin_zlib) +# Request explicit user opt-in for required dependencies +if(asimage) + ROOT_FIND_REQUIRED_DEP(GIF builtin_gif) + ROOT_FIND_REQUIRED_DEP(JPEG builtin_jpeg) + # We cannot PNG here because while searching PNG, CMake will also find ZLIB. + # If found, CMake will define the default variables and target: + # see https://cmake.org/cmake/help/latest/module/FindZLIB.html). + # For this reason, the check has to be put below, after ZLIB is searched for. + #ROOT_FIND_REQUIRED_DEP(PNG builtin_png) +endif() +ROOT_FIND_REQUIRED_DEP(LZ4 builtin_lz4) ROOT_FIND_REQUIRED_DEP(LibLZMA builtin_lzma) +ROOT_FIND_REQUIRED_DEP(ZLIB builtin_zlib) ROOT_FIND_REQUIRED_DEP(ZSTD builtin_zstd) -ROOT_FIND_REQUIRED_DEP(LZ4 builtin_lz4) if(NOT "${MISSING_PACKAGES}" STREQUAL "") message(FATAL_ERROR "The following packages need to be installed or enabled to build ROOT: ${MISSING_PACKAGES}") @@ -120,7 +130,7 @@ endif() #--- Redefine find_package for LLVM to pick up ROOT's builtins ---------------------- # TODO: Make this only local to LLVM? macro(find_package) - if(NOT "${ARGV0}" IN_LIST ROOT_BUILTINS) + if(NOT "${ARGV0}" IN_LIST ROOT_BUILTINS) # ROOT_BUILTINS are the variable names, not the same as ROOT_BUILTIN_TARGETS used for move-header dependency _find_package(${ARGV}) endif() endmacro() @@ -142,6 +152,29 @@ endif() if(builtin_zlib) list(APPEND ROOT_BUILTINS ZLIB) add_subdirectory(builtins/zlib) +else() + # If not built-in, check if this is zlib-ng + set(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS}) + message(STATUS "Checking whether zlib-ng is provided") + check_c_source_compiles(" + #include + #ifndef ZLIBNG_VERNUM + #error Not zlib-ng + #endif + int main() { return 0; } + " ZLIB_NG) +endif() + +if(ZLIB_NG) + message(STATUS "Zlib-ng detected") +else() + message(STATUS "Zlib detected") +endif() + +if(asimage) + # This check can be added only now because of the reasons explained above, where all + # other required dependencies are checked. + ROOT_FIND_REQUIRED_DEP(PNG builtin_png) endif() #---Check for nlohmann/json.hpp--------------------------------------------------------- @@ -212,86 +245,10 @@ if(unuran AND NOT builtin_unuran) endif() #---Check for Freetype--------------------------------------------------------------- -if(NOT builtin_freetype) - message(STATUS "Looking for Freetype") - if(fail-on-missing) - find_package(Freetype REQUIRED) - else() - find_package(Freetype) - if(FREETYPE_FOUND) - set(FREETYPE_INCLUDE_DIR ${FREETYPE_INCLUDE_DIR_freetype2}) - else() - message(STATUS "FreeType not found. Switching on builtin_freetype option") - set(builtin_freetype ON CACHE BOOL "Enabled because FreeType not found (${builtin_freetype_description})" FORCE) - endif() - endif() -endif() - +ROOT_FIND_REQUIRED_DEP(Freetype builtin_freetype) # needed for asimage, but also outside of it (for "graf" target) if(builtin_freetype) - set(freetype_version 2.12.1) - message(STATUS "Building freetype version ${freetype_version} included in ROOT itself") - set(FREETYPE_LIBRARY ${CMAKE_BINARY_DIR}/FREETYPE-prefix/src/FREETYPE/objs/.libs/${CMAKE_STATIC_LIBRARY_PREFIX}freetype${CMAKE_STATIC_LIBRARY_SUFFIX}) - if(WIN32) - set(FREETYPE_LIB_DIR ".") - if(CMAKE_GENERATOR MATCHES Ninja) - set(freetypelib freetype.lib) - if (CMAKE_BUILD_TYPE MATCHES Debug) - set(freetypelib freetyped.lib) - endif() - else() - set(freetypebuild Release) - set(freetypelib freetype.lib) - if(winrtdebug) - set(freetypebuild Debug) - set(freetypelib freetyped.lib) - endif() - set(FREETYPE_LIB_DIR "${freetypebuild}") - set(FREETYPE_EXTRA_BUILD_ARGS --config ${freetypebuild}) - endif() - ExternalProject_Add( - FREETYPE - URL ${CMAKE_SOURCE_DIR}/graf2d/freetype/src/freetype-${freetype_version}.tar.gz - URL_HASH SHA256=efe71fd4b8246f1b0b1b9bfca13cfff1c9ad85930340c27df469733bbb620938 - INSTALL_DIR ${CMAKE_BINARY_DIR} - CMAKE_ARGS -G ${CMAKE_GENERATOR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DFT_DISABLE_BZIP2=TRUE - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 - BUILD_COMMAND ${CMAKE_COMMAND} --build . ${FREETYPE_EXTRA_BUILD_ARGS} - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FREETYPE_LIB_DIR}/${freetypelib} ${FREETYPE_LIBRARY} - LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 - BUILD_IN_SOURCE 0 - BUILD_BYPRODUCTS ${FREETYPE_LIBRARY} - TIMEOUT 600 - ) - else() - set(_freetype_cflags -O) - set(_freetype_cc ${CMAKE_C_COMPILER}) - if(CMAKE_SYSTEM_NAME STREQUAL AIX) - set(_freetype_zlib --without-zlib) - endif() - set(_freetype_brotli "--with-brotli=no") - if(CMAKE_OSX_SYSROOT) - set(_freetype_cc "${_freetype_cc} -isysroot ${CMAKE_OSX_SYSROOT}") - endif() - ExternalProject_Add( - FREETYPE - URL ${CMAKE_SOURCE_DIR}/graf2d/freetype/src/freetype-${freetype_version}.tar.gz - URL_HASH SHA256=efe71fd4b8246f1b0b1b9bfca13cfff1c9ad85930340c27df469733bbb620938 - CONFIGURE_COMMAND ./configure --prefix --with-pic - --disable-shared --with-png=no --with-bzip2=no - --with-harfbuzz=no ${_freetype_brotli} ${_freetype_zlib} - "CC=${_freetype_cc}" CFLAGS=${_freetype_cflags} - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 - BUILD_IN_SOURCE 1 - BUILD_BYPRODUCTS ${FREETYPE_LIBRARY} - TIMEOUT 600 - ) - endif() - set(FREETYPE_INCLUDE_DIR ${CMAKE_BINARY_DIR}/FREETYPE-prefix/src/FREETYPE/include) - set(FREETYPE_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIR}) - set(FREETYPE_LIBRARIES ${FREETYPE_LIBRARY}) - set(FREETYPE_TARGET FREETYPE) + list(APPEND ROOT_BUILTINS BUILTIN_FREETYPE) + add_subdirectory(builtins/freetype) endif() #---Check for Cocoa/Quartz graphics backend (MacOS X only)--------------------------- @@ -405,176 +362,39 @@ if(asimage) endif() if(asimage) - if(NOT builtin_gif) - find_Package(GIF) - if(GIF_FOUND) - list(APPEND ASEXTRA_LIBRARIES GIF::GIF) - else() - if(fail-on-missing) - message(SEND_ERROR "Dependency libgif not found. Please make sure it's installed on the system, or force the builtin libgif with '-Dbuiltin_gif=ON', or set '-Dfail-on-missing=OFF' to fall back to builtins if a dependency is not found.") - else() - set(builtin_gif ON CACHE BOOL "Enabled because needed for asimage" FORCE) - endif() - endif() - endif() - if(builtin_gif) add_subdirectory(builtins/libgif) get_target_property(GIF_INCLUDE_DIR GIF::GIF INTERFACE_INCLUDE_DIRECTORIES) get_target_property(GIF_LIBRARY_LOCATION GIF::GIF IMPORTED_LOCATION) endif() - - if(NOT builtin_png) - find_Package(PNG) - if(PNG_FOUND) - list(APPEND ASEXTRA_LIBRARIES PNG::PNG) - # apparently there will be two set of includes here (needs to be selected only last that was passed: PNG_INCLUDE_DIR) - list(GET PNG_INCLUDE_DIRS 0 PNG_INCLUDE_DIR) - else() - if(fail-on-missing) - message(SEND_ERROR "Dependency libpng not found. Please make sure it's installed on the system, or force the builtin libpng with '-Dbuiltin_png=ON', or set '-Dfail-on-missing=OFF' to fall back to builtins if a dependency is not found.") - else() - set(builtin_png ON CACHE BOOL "Enabled because needed for asimage" FORCE) - endif() - endif() - endif() + list(APPEND ASEXTRA_LIBRARIES GIF::GIF) if(builtin_png) add_subdirectory(builtins/libpng) get_target_property(PNG_INCLUDE_DIR PNG::PNG INTERFACE_INCLUDE_DIRECTORIES) get_target_property(PNG_LIBRARY_LOCATION PNG::PNG IMPORTED_LOCATION) endif() - - if(NOT builtin_jpeg) - find_Package(JPEG) - if(JPEG_FOUND) - list(APPEND ASEXTRA_LIBRARIES JPEG::JPEG) - else() - if(fail-on-missing) - message(SEND_ERROR "Dependency libjpeg not found. Please make sure it's installed on the system, or force the builtin libjpeg with '-Dbuiltin_jpeg=ON', or set '-Dfail-on-missing=OFF' to fall back to builtins if a dependency is not found.") - else() - set(builtin_jpeg ON CACHE BOOL "Enabled because needed for asimage" FORCE) - endif() - endif() - endif() + list(APPEND ASEXTRA_LIBRARIES PNG::PNG) if(builtin_jpeg) add_subdirectory(builtins/libjpeg) get_target_property(JPEG_INCLUDE_DIR JPEG::JPEG INTERFACE_INCLUDE_DIRECTORIES) get_target_property(JPEG_LIBRARY_LOCATION JPEG::JPEG IMPORTED_LOCATION) endif() - + list(APPEND ASEXTRA_LIBRARIES JPEG::JPEG) + if(asimage_tiff) find_Package(TIFF) if(TIFF_FOUND) list(APPEND ASEXTRA_LIBRARIES TIFF::TIFF) else() if(fail-on-missing) - message(SEND_ERROR "Dependency libtiff not found. Please make sure it's installed on the system, or disable TIFF support with '-Dasimage_tiff=OFF', or set '-Dfail-on-missing=OFF' to automatically disable features") + message(SEND_ERROR "libtiff required but not found. Please make sure it's installed on the system, or disable TIFF support with '-Dasimage_tiff=OFF', or set '-Dfail-on-missing=OFF' to automatically disable features") else() set(asimage_tiff OFF CACHE BOOL "Disabled because libtiff was not found" FORCE) endif() endif() endif() - - #---AfterImage--------------------------------------------------------------- - set(AFTERIMAGE_LIBRARIES ${CMAKE_BINARY_DIR}/lib/libAfterImage${CMAKE_STATIC_LIBRARY_SUFFIX}) - if(WIN32) - set(ASTEP_LIB_DIR ".") - if(NOT CMAKE_GENERATOR MATCHES Ninja) - if(winrtdebug) - set(astepbld Debug) - else() - set(astepbld Release) - endif() - set(ASTEP_LIB_DIR "${astepbld}") - set(ASTEP_EXTRA_BUILD_ARGS --config ${astepbld}) - endif() - ExternalProject_Add( - AFTERIMAGE - DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/graf2d/asimage/src/libAfterImage AFTERIMAGE - INSTALL_DIR ${CMAKE_BINARY_DIR} - CMAKE_ARGS -G ${CMAKE_GENERATOR} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DFREETYPE_INCLUDE_DIR=${FREETYPE_INCLUDE_DIR} - -DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR} - -DJPEG_INCLUDE_DIR=${JPEG_INCLUDE_DIR} - -DJPEG_LIBRARY_LOCATION=${JPEG_LIBRARY_LOCATION} - -DPNG_INCLUDE_DIR=${PNG_INCLUDE_DIR} - -DPNG_LIBRARY_LOCATION=${PNG_LIBRARY_LOCATION} - -DGIF_INCLUDE_DIR=${GIF_INCLUDE_DIR} - -DGIF_LIBRARY_LOCATION=${GIF_LIBRARY_LOCATION} - BUILD_COMMAND ${CMAKE_COMMAND} --build . ${ASTEP_EXTRA_BUILD_ARGS} - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ASTEP_LIB_DIR}/libAfterImage.lib /lib/ - LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 - BUILD_IN_SOURCE 0 - BUILD_BYPRODUCTS ${AFTERIMAGE_LIBRARIES} - TIMEOUT 600 - ) - set(AFTERIMAGE_INCLUDE_DIR ${CMAKE_BINARY_DIR}/AFTERIMAGE-prefix/src/AFTERIMAGE) - else() - if(asimage_tiff) - list(APPEND afterimage_extra_args --with-tiff-includes=${TIFF_INCLUDE_DIR}) - else() - list(APPEND afterimage_extra_args --with-tiff=no) - endif() - if(x11) - list(APPEND afterimage_extra_args --with-x) - else() - list(APPEND afterimage_extra_args --without-x) - endif() - if(builtin_freetype) - list(APPEND afterimage_extra_args --with-ttf-includes=-I${FREETYPE_INCLUDE_DIR}) - set(_after_cflags "${_after_cflags} -DHAVE_FREETYPE_FREETYPE -DPNG_ARM_NEON_OPT=0") - endif() - if(CMAKE_OSX_SYSROOT) - set(_after_cflags "${_after_cflags} -isysroot ${CMAKE_OSX_SYSROOT}") - endif() - if(builtin_zlib) - set(_after_cflags "${_after_cflags} -I${ZLIB_INCLUDE_DIR}") - endif() - if(CMAKE_SYSTEM_NAME MATCHES FreeBSD) - set(AFTERIMAGE_LIBRARIES ${CMAKE_BINARY_DIR}/AFTERIMAGE-prefix/src/AFTERIMAGE/libAfterImage${CMAKE_STATIC_LIBRARY_SUFFIX}) - endif() - ExternalProject_Add( - AFTERIMAGE - DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/graf2d/asimage/src/libAfterImage AFTERIMAGE - INSTALL_DIR ${CMAKE_BINARY_DIR} - CONFIGURE_COMMAND ./configure --prefix - --libdir=/lib - --with-ttf --with-afterbase=no - --without-svg --disable-glx - --with-jpeg - --with-jpeg-includes=${JPEG_INCLUDE_DIR} - --with-png - --with-png-includes=${PNG_INCLUDE_DIR} - --with-gif - --with-gif-includes=${GIF_INCLUDE_DIR} - ${afterimage_extra_args} - CC=${CMAKE_C_COMPILER} CFLAGS=${_after_cflags} - LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 LOG_OUTPUT_ON_FAILURE 1 - BUILD_IN_SOURCE 1 - BUILD_BYPRODUCTS ${AFTERIMAGE_LIBRARIES} - TIMEOUT 600 - ) - set(AFTERIMAGE_INCLUDE_DIR ${CMAKE_BINARY_DIR}/include/libAfterImage) - if(CMAKE_SYSTEM_NAME MATCHES FreeBSD) - set(AFTERIMAGE_INCLUDE_DIR ${CMAKE_BINARY_DIR}/AFTERIMAGE-prefix/src/AFTERIMAGE) - endif() - endif() - if(builtin_gif) - add_dependencies(AFTERIMAGE BUILTIN_LIBGIF) - endif() - if(builtin_jpeg) - add_dependencies(AFTERIMAGE BUILTIN_LIBJPEG) - endif() - if(builtin_png) - add_dependencies(AFTERIMAGE BUILTIN_LIBPNG) - endif() - if(builtin_freetype) - add_dependencies(AFTERIMAGE FREETYPE) - endif() - set(AFTERIMAGE_TARGET AFTERIMAGE) endif() #---Check for GSL library--------------------------------------------------------------- @@ -689,21 +509,18 @@ endif() # features also depend on asimage. Therefore, the configuration will fail if # asimage is off. See also: https://github.com/root-project/root/issues/16250 if(opengl AND NOT asimage) - message(FATAL_ERROR "OpenGL features enabled with \"opengl=ON\" require \"asimage=ON\"") + message(SEND_ERROR "OpenGL features enabled with \"opengl=ON\" require \"asimage=ON\"") endif() #---Check for gl2ps ------------------------------------------------------------------ -if(opengl AND NOT builtin_gl2ps) - message(STATUS "Looking for gl2ps") - if(fail-on-missing) - find_Package(gl2ps REQUIRED) - else() - find_Package(gl2ps) - if(NOT GL2PS_FOUND) - message(STATUS "gl2ps not found. Switching on builtin_gl2ps option") - set(builtin_gl2ps ON CACHE BOOL "Enabled because opengl requested and gl2ps not found (${builtin_gl2ps_description})" FORCE) - endif() +if(opengl) + ROOT_FIND_REQUIRED_DEP(gl2ps builtin_gl2ps) + if (builtin_gl2ps) + add_subdirectory(builtins/gl2ps) + list(APPEND ROOT_BUILTINS BUILTIN_GL2PS) endif() +elseif(builtin_gl2ps) + message(SEND_ERROR "gl2ps features enabled with \"builtin_gl2ps=ON\" require \"opengl=ON\"") endif() #---Check for Graphviz installation------------------------------------------------------- @@ -754,8 +571,7 @@ if(ssl AND NOT builtin_openssl) message(STATUS "OpenSSL not found, and no internet connection. Disabling the 'ssl' option.") set(ssl OFF CACHE BOOL "Disabled because ssl requested and OpenSSL not found (${builtin_openssl_description}) and there is no internet connection" FORCE) else() - message(STATUS "OpenSSL not found, switching ON 'builtin_openssl' option.") - set(builtin_openssl ON CACHE BOOL "Enabled because ssl requested and OpenSSL not found (${builtin_openssl_description})" FORCE) + message(SEND_ERROR "OpenSSL required but not found. Install it on the system (preferred), or explicitly request the builtin version.") endif() endif() endif() @@ -916,6 +732,14 @@ if(xrootd AND NOT builtin_xrootd) set(builtin_xrootd ON CACHE BOOL "Enabled because xrootd is enabled, but external xrootd was not found (${xrootd_description})" FORCE) endif() endif() + else() + # XROOTD was found. Check now for required components + foreach (component CLIENT UTILS) # ROOT requires XrdCl and XrdUtils + if("${XROOTD_${component}_LIBRARIES}" STREQUAL "XROOTD_${component}_LIBRARIES-NOTFOUND") + message(SEND_ERROR "XROOTD found but missing component ${component}. Install missing package on your system (preferred). " + "Alternatively, you can also enable the option 'builtin_xrootd' to build XROOTD internally") + endif() + endforeach() endif() if(XRootD_VERSION VERSION_LESS 5.8.4) @@ -1512,13 +1336,6 @@ if(tmva) message(STATUS "TMVA: Numpy or Python development package not found for python ${Python3_EXECUTABLE}. Switching off tmva-pymva option") set(tmva-pymva OFF CACHE BOOL "Disabled because Numpy or Python development package were not found (${tmva-pymva_description})" FORCE) endif() - if(testing) - message(STATUS "Looking for BLAS as an optional testing dependency of PyMVA") - find_package(BLAS) - if(NOT BLAS_FOUND) - message(WARNING "BLAS not found: PyMVA will not be fully tested") - endif() - endif() endif() if (R_FOUND) #Rmva is enable when r is found and tmva is on @@ -1865,8 +1682,8 @@ if(webgui) endif() ExternalProject_Add( RENDERCORE - URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore-1.8.tar.gz - URL_HASH SHA256=2ab84800ec1aaf36671e463a09e3befbe97b06b2547f97ec05fe16ef1351c79a + URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore-1.9.tar.gz + URL_HASH SHA256=7728f00ee5e907c36b25aad56fbc73881c7c9faf47a36bee5efd2054bc4ecc6c CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/config/RConfigure.in b/config/RConfigure.in index a0e683ede7a8a..7c81b9dd28025 100644 --- a/config/RConfigure.in +++ b/config/RConfigure.in @@ -53,11 +53,7 @@ #@use_less_includes@ R__LESS_INCLUDES /**/ #define R__HARDWARE_INTERFERENCE_SIZE @hardwareinterferencesize@ /*Determined at CMake configure to be stable across all TUs*/ -#@uselz4@ R__HAS_DEFAULT_LZ4 /**/ -#@usezlib@ R__HAS_DEFAULT_ZLIB /**/ -#@uselzma@ R__HAS_DEFAULT_LZMA /**/ -#@usezstd@ R__HAS_DEFAULT_ZSTD /**/ -#@usecloudflarezlib@ R__HAS_CLOUDFLARE_ZLIB /**/ +#@usezlibng@ R__HAS_ZLIB_NG /**/ #@hastmvacpu@ R__HAS_TMVACPU /**/ #@hastmvagpu@ R__HAS_TMVAGPU /**/ diff --git a/config/rootrc.in b/config/rootrc.in index 265d80e5d4026..af28757d2e986 100644 --- a/config/rootrc.in +++ b/config/rootrc.in @@ -174,20 +174,6 @@ Hist.Stats.KurtosisX: Kurtosis x Hist.Stats.KurtosisY: Kurtosis y Hist.Stats.KurtosisZ: Kurtosis z -# THtml specific settings (for more see doc of THtml class). -Root.Html.SourceDir: . -Root.Html.Root: http://root.cern.ch/root/html -Root.Html.ViewCVS: http://root.cern.ch/viewcvs/trunk/%f?view=log -Root.Html.Search: http://www.google.com/search?q=%s+site%3A%u+-site%3A%u%2Fsrc%2F+-site%3A%u%2Fexamples%2F -#Root.Html.OutputDir: htmldoc/ -#Root.Html.Homepage: -#Root.Html.Header: -#Root.Html.Footer: -#Root.Html.Description: //____________________ -#Root.Html.Author: // Author: -#Root.Html.LastUpdate: // @(#) -#Root.Html.Copyright: * Copyright - # GUI specific settings. Gui.Backend: native Gui.Factory: native diff --git a/core/base/inc/TAttFill.h b/core/base/inc/TAttFill.h index 32c64d778b3d5..5fc086efbcac5 100644 --- a/core/base/inc/TAttFill.h +++ b/core/base/inc/TAttFill.h @@ -32,7 +32,7 @@ class TAttFill { virtual Color_t GetFillColor() const { return fFillColor; } ///< Return the fill area color virtual Style_t GetFillStyle() const { return fFillStyle; } ///< Return the fill area style virtual Bool_t IsTransparent() const; - virtual void ModifyOn(TVirtualPad *pad); + virtual void ModifyOn(TVirtualPad &pad); virtual void Modify(); virtual void ResetAttFill(Option_t *option=""); virtual void SaveFillAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1001); diff --git a/core/base/inc/TAttLine.h b/core/base/inc/TAttLine.h index 7d90ce1af1c4d..246f752589587 100644 --- a/core/base/inc/TAttLine.h +++ b/core/base/inc/TAttLine.h @@ -37,7 +37,7 @@ class TAttLine { virtual Style_t GetLineStyle() const {return fLineStyle;} ///< Return the line style virtual Width_t GetLineWidth() const {return fLineWidth;} ///< Return the line width virtual void Modify(); - virtual void ModifyOn(TVirtualPad *pad); + virtual void ModifyOn(TVirtualPad &pad); virtual void ResetAttLine(Option_t *option=""); virtual void SaveLineAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t widdef=1); virtual void SetLineAttributes(); // *MENU* diff --git a/core/base/inc/TAttMarker.h b/core/base/inc/TAttMarker.h index 46dfb61412aed..765cf574975da 100644 --- a/core/base/inc/TAttMarker.h +++ b/core/base/inc/TAttMarker.h @@ -34,7 +34,7 @@ class TAttMarker { virtual Style_t GetMarkerStyle() const {return fMarkerStyle;} ///< Return the marker style virtual Size_t GetMarkerSize() const {return fMarkerSize;} ///< Return the marker size virtual void Modify(); - virtual void ModifyOn(TVirtualPad *pad); + virtual void ModifyOn(TVirtualPad &pad); virtual void ResetAttMarker(Option_t *toption=""); virtual void SaveMarkerAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t sizdef=1); virtual void SetMarkerAttributes(); // *MENU* diff --git a/core/base/inc/TAttText.h b/core/base/inc/TAttText.h index ce46d6523f4a6..d857a257facc0 100644 --- a/core/base/inc/TAttText.h +++ b/core/base/inc/TAttText.h @@ -39,7 +39,7 @@ class TAttText { virtual Float_t GetTextSize() const {return fTextSize;} ///< Return the text size virtual Float_t GetTextSizePercent(Float_t size); ///< Return the text in percent of the pad size virtual void Modify(); - virtual void ModifyOn(TVirtualPad *pad); + virtual void ModifyOn(TVirtualPad &pad); virtual void ResetAttText(Option_t *toption=""); virtual void SaveTextAttributes(std::ostream &out, const char *name, Int_t alidef=12, Float_t angdef=0, Int_t coldef=1, Int_t fondef=61, Float_t sizdef=1); virtual void SetTextAttributes(); // *MENU* diff --git a/core/base/inc/TVirtualPadPainter.h b/core/base/inc/TVirtualPadPainter.h index 830d0bc8acb4e..778047cc7f8ba 100644 --- a/core/base/inc/TVirtualPadPainter.h +++ b/core/base/inc/TVirtualPadPainter.h @@ -13,8 +13,14 @@ #define ROOT_TVirtualPadPainter #include "Rtypes.h" +#include "GuiTypes.h" class TVirtualPad; +class TVirtualPS; +class TAttFill; +class TAttLine; +class TAttMarker; +class TAttText; class TVirtualPadPainter { public: @@ -75,6 +81,16 @@ class TVirtualPadPainter { virtual void SetMarkerStyle(Style_t /* mstyle */ = 1) {} virtual void SetMarkerSize(Size_t /* msize */ = 1) {} + virtual void SetAttFill(const TAttFill &att); + virtual void SetAttLine(const TAttLine &att); + virtual void SetAttMarker(const TAttMarker &att); + virtual void SetAttText(const TAttText &att); + + virtual const TAttFill &GetAttFill() const; + virtual const TAttLine &GetAttLine() const; + virtual const TAttMarker &GetAttMarker() const; + virtual const TAttText &GetAttText() const; + //This part is an interface to X11 pixmap management and to save sub-pads off-screens for OpenGL. //Currently, must be implemented only for X11/GDI virtual Int_t CreateDrawable(UInt_t w, UInt_t h) = 0;//gVirtualX->OpenPixmap @@ -83,6 +99,11 @@ class TVirtualPadPainter { virtual void CopyDrawable(Int_t device, Int_t px, Int_t py) = 0; virtual void DestroyDrawable(Int_t device) = 0;//gVirtualX->CloseWindow virtual void SelectDrawable(Int_t device) = 0;//gVirtualX->SelectWindow + virtual void UpdateDrawable(Int_t /* mode */) {} + virtual void SetDrawMode(Int_t /* device */, Int_t /* mode */) {} + virtual void SetDoubleBuffer(Int_t device, Int_t mode); + virtual void SetCursor(Int_t win, ECursor cursor); + //TASImage support. virtual void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, @@ -127,6 +148,8 @@ class TVirtualPadPainter { virtual Bool_t IsNative() const { return kFALSE; } virtual Bool_t IsCocoa() const { return kFALSE; } + virtual TVirtualPS *GetPS() const { return nullptr; } + virtual Bool_t IsSupportAlpha() const { return kFALSE; } static TVirtualPadPainter *PadPainter(Option_t *opt = ""); diff --git a/core/base/inc/TVirtualX.h b/core/base/inc/TVirtualX.h index 6ab0aea521a81..ddbae75d26dbc 100644 --- a/core/base/inc/TVirtualX.h +++ b/core/base/inc/TVirtualX.h @@ -67,13 +67,26 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual void CreateOpenGLContext(Int_t wid=0); virtual void DeleteOpenGLContext(Int_t wid=0); - //---- OpenGL related stuff, required only with R__HAS_COCOA ---- - virtual Double_t GetOpenGLScalingFactor(); - virtual Window_t CreateOpenGLWindow(Window_t parentID, UInt_t width, UInt_t height, const std::vector > &format); - virtual Handle_t CreateOpenGLContext(Window_t windowID, Handle_t sharedContext); - virtual Bool_t MakeOpenGLContextCurrent(Handle_t ctx, Window_t windowID); - virtual Handle_t GetCurrentOpenGLContext(); - virtual void FlushOpenGLBuffer(Handle_t ctx); + + //---- Old graphics interface ----- + + void SetFillColor(Color_t cindex) override; + void SetFillStyle(Style_t style) override; + void SetLineColor(Color_t cindex) override; + virtual void SetLineType(Int_t n, Int_t *dash); + void SetLineStyle(Style_t linestyle) override; + void SetLineWidth(Width_t width) override; + void SetMarkerColor(Color_t cindex) override; + void SetMarkerSize(Float_t markersize) override; + void SetMarkerStyle(Style_t markerstyle) override; + virtual void SetOpacity(Int_t percent); + virtual void SetRGB(Int_t cindex, Float_t r, Float_t g, Float_t b); + void SetTextAlign(Short_t talign=11) override; + void SetTextColor(Color_t cindex) override; + virtual Int_t SetTextFont(char *fontname, ETextSetMode mode); + void SetTextFont(Font_t fontnumber) override; + virtual void SetTextMagnitude(Float_t mgn); + void SetTextSize(Float_t textsize) override; virtual void DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode); virtual void DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, @@ -87,6 +100,37 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe ETextMode mode); virtual void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode); + + //---- New graphics interface ----- + + virtual WinContext_t GetWindowContext(Int_t wid); + virtual void SetAttFill(WinContext_t wctxt, const TAttFill &att); + virtual void SetAttLine(WinContext_t wctxt, const TAttLine &att); + virtual void SetAttMarker(WinContext_t wctxt, const TAttMarker &att); + virtual void SetAttText(WinContext_t wctxt, const TAttText &att); + virtual void SetDrawModeW(WinContext_t wctxt, EDrawMode mode); + virtual EDrawMode GetDrawModeW(WinContext_t wctxt); + virtual void ClearWindowW(WinContext_t wctxt); + virtual void UpdateWindowW(WinContext_t wctxt, Int_t mode); + + virtual void DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode); + virtual void DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy); + virtual void DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2); + virtual void DrawPolyLineW(WinContext_t wctxt, Int_t n, TPoint *xy); + virtual void DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xy); + virtual void DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xy); + virtual void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode); + virtual void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode); + + + //---- OpenGL related stuff, required only with R__HAS_COCOA ---- + virtual Double_t GetOpenGLScalingFactor(); + virtual Window_t CreateOpenGLWindow(Window_t parentID, UInt_t width, UInt_t height, const std::vector > &format); + virtual Handle_t CreateOpenGLContext(Window_t windowID, Handle_t sharedContext); + virtual Bool_t MakeOpenGLContextCurrent(Handle_t ctx, Window_t windowID); + virtual Handle_t GetCurrentOpenGLContext(); + virtual void FlushOpenGLBuffer(Handle_t ctx); + virtual UInt_t ExecCommand(TGWin32Command *code); virtual void GetCharacterUp(Float_t &chupx, Float_t &chupy); EDrawMode GetDrawMode() { return fDrawMode; } @@ -129,23 +173,6 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual void SetDoubleBufferOFF(); virtual void SetDoubleBufferON(); virtual void SetDrawMode(EDrawMode mode); - void SetFillColor(Color_t cindex) override; - void SetFillStyle(Style_t style) override; - void SetLineColor(Color_t cindex) override; - virtual void SetLineType(Int_t n, Int_t *dash); - void SetLineStyle(Style_t linestyle) override; - void SetLineWidth(Width_t width) override; - void SetMarkerColor(Color_t cindex) override; - void SetMarkerSize(Float_t markersize) override; - void SetMarkerStyle(Style_t markerstyle) override; - virtual void SetOpacity(Int_t percent); - virtual void SetRGB(Int_t cindex, Float_t r, Float_t g, Float_t b); - void SetTextAlign(Short_t talign=11) override; - void SetTextColor(Color_t cindex) override; - virtual Int_t SetTextFont(char *fontname, ETextSetMode mode); - void SetTextFont(Font_t fontnumber) override; - virtual void SetTextMagnitude(Float_t mgn); - void SetTextSize(Float_t textsize) override; virtual void Sync(Int_t mode); virtual void UpdateWindow(Int_t mode); virtual void Warp(Int_t ix, Int_t iy, Window_t id = 0); diff --git a/core/base/src/TAttFill.cxx b/core/base/src/TAttFill.cxx index c639697e0e9eb..257318a061268 100644 --- a/core/base/src/TAttFill.cxx +++ b/core/base/src/TAttFill.cxx @@ -215,19 +215,18 @@ void TAttFill::Copy(TAttFill &attfill) const void TAttFill::Modify() { - ModifyOn(gPad); + if (gPad) + ModifyOn(*gPad); } //////////////////////////////////////////////////////////////////////////////// /// Change current fill area attributes on speicifed pad -void TAttFill::ModifyOn(TVirtualPad *pad) +void TAttFill::ModifyOn(TVirtualPad &pad) { - auto pp = pad ? pad->GetPainter() : nullptr; - if (!pp) - return; - pp->SetFillColor(fFillColor); - pp->SetFillStyle(fFillStyle); + auto pp = pad.GetPainter(); + if (pp) + pp->SetAttFill(*this); } //////////////////////////////////////////////////////////////////////////////// diff --git a/core/base/src/TAttLine.cxx b/core/base/src/TAttLine.cxx index 23dae3e5c3386..e001ca4ac20c8 100644 --- a/core/base/src/TAttLine.cxx +++ b/core/base/src/TAttLine.cxx @@ -245,22 +245,33 @@ Int_t TAttLine::DistancetoLine(Int_t px, Int_t py, Double_t xp1, Double_t yp1, D void TAttLine::Modify() { - ModifyOn(gPad); + if (gPad) + ModifyOn(*gPad); } //////////////////////////////////////////////////////////////////////////////// /// Change current line attributes on specified pad -void TAttLine::ModifyOn(TVirtualPad *pad) +void TAttLine::ModifyOn(TVirtualPad &pad) { - auto pp = pad ? pad->GetPainter() : nullptr; + auto pp = pad.GetPainter(); if (!pp) return; - pp->SetLineColor(fLineColor); - pp->SetLineStyle((fLineStyle > 0 && fLineStyle < 30) ? fLineStyle : 1); - pp->SetLineWidth(std::abs(fLineWidth % 100)); -} + Bool_t normal_style = (fLineStyle > 0) && (fLineStyle < 30); + Bool_t normal_width = (fLineWidth >= 0) && (fLineWidth < 100); + + if (normal_style && normal_width) + pp->SetAttLine(*this); + else { + TAttLine att1(*this); + if (!normal_style) + att1.SetLineStyle(1); + if (!normal_width) + att1.SetLineWidth(std::abs(fLineWidth % 100)); + pp->SetAttLine(att1); + } +} //////////////////////////////////////////////////////////////////////////////// /// Reset this line attributes to default values. diff --git a/core/base/src/TAttMarker.cxx b/core/base/src/TAttMarker.cxx index da84a7266dc22..97b85c36aa3bd 100644 --- a/core/base/src/TAttMarker.cxx +++ b/core/base/src/TAttMarker.cxx @@ -321,21 +321,18 @@ Width_t TAttMarker::GetMarkerLineWidth(Style_t style) void TAttMarker::Modify() { - ModifyOn(gPad); + if (gPad) + ModifyOn(*gPad); } //////////////////////////////////////////////////////////////////////////////// /// Change current marker attributes if necessary on specified pad. -void TAttMarker::ModifyOn(TVirtualPad *pad) +void TAttMarker::ModifyOn(TVirtualPad &pad) { - auto pp = pad ? pad->GetPainter() : nullptr; - if (!pp) - return; - - pp->SetMarkerColor(fMarkerColor); - pp->SetMarkerSize (fMarkerSize); - pp->SetMarkerStyle(fMarkerStyle); + auto pp = pad.GetPainter(); + if (pp) + pp->SetAttMarker(*this); } diff --git a/core/base/src/TAttText.cxx b/core/base/src/TAttText.cxx index 2aee8a5a5cd78..2e078add3b152 100644 --- a/core/base/src/TAttText.cxx +++ b/core/base/src/TAttText.cxx @@ -326,51 +326,49 @@ Float_t TAttText::GetTextSizePercent(Float_t size) void TAttText::Modify() { - ModifyOn(gPad); + if (gPad) + ModifyOn(*gPad); } - //////////////////////////////////////////////////////////////////////////////// /// Change current text attributes if necessary on specified pad. -void TAttText::ModifyOn(TVirtualPad *pad) +void TAttText::ModifyOn(TVirtualPad &pad) { - auto pp = pad ? pad->GetPainter() : nullptr; + auto pp = pad.GetPainter(); if (!pp) return; + Float_t tsize0 = fTextSize; Float_t tsize = fTextSize; // there was difference in text size handling, keep it in one place if (pp->IsNative()) { if (fTextFont % 10 <= 2) { - auto wh = pad->XtoPixel(pad->GetX2()); - auto hh = pad->YtoPixel(pad->GetY1()); + auto wh = pad.XtoPixel(pad.GetX2()); + auto hh = pad.YtoPixel(pad.GetY1()); if (wh < hh) tsize *= wh; else tsize *= hh; } } else { if (fTextFont % 10 > 2) { - Float_t wh = pad->XtoPixel(pad->GetX2()); - Float_t hh = pad->YtoPixel(pad->GetY1()); + Float_t wh = pad.XtoPixel(pad.GetX2()); + Float_t hh = pad.YtoPixel(pad.GetY1()); if (wh < hh) { - Float_t dy = pad->AbsPixeltoX(Int_t(tsize)) - pad->AbsPixeltoX(0); - tsize = dy/(pad->GetX2() - pad->GetX1()); + Float_t dy = pad.AbsPixeltoX(Int_t(tsize)) - pad.AbsPixeltoX(0); + tsize = dy/(pad.GetX2() - pad.GetX1()); } else { - Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY(Int_t(tsize)); - tsize = dy/(pad->GetY2() - pad->GetY1()); + Float_t dy = pad.AbsPixeltoY(0) - pad.AbsPixeltoY(Int_t(tsize)); + tsize = dy/(pad.GetY2() - pad.GetY1()); } } } - pp->SetTextAngle(fTextAngle); - if (pp->GetTextFont() != fTextFont) { - pp->SetTextFont(fTextFont); - pp->SetTextSize(tsize); - } else if (pp->GetTextSize() != tsize) { - pp->SetTextSize(tsize); - } - pp->SetTextAlign(fTextAlign); - pp->SetTextColor(fTextColor); + + fTextSize = tsize; + + pp->SetAttText(*this); + + fTextSize = tsize0; } diff --git a/core/base/src/TBuffer.cxx b/core/base/src/TBuffer.cxx index 8a0c2b78e99e6..20cba8b524a37 100644 --- a/core/base/src/TBuffer.cxx +++ b/core/base/src/TBuffer.cxx @@ -304,6 +304,7 @@ void TBuffer::SetReadMode() // We had reserved space for the free block count, // release it, fBufSize += kExtraSpace; + fBufMax = fBuffer + fBufSize; } fMode = kRead; } @@ -317,6 +318,7 @@ void TBuffer::SetWriteMode() // We had not yet reserved space for the free block count, // reserve it now. fBufSize -= kExtraSpace; + fBufMax = fBuffer + fBufSize; } fMode = kWrite; } diff --git a/core/base/src/TDirectory.cxx b/core/base/src/TDirectory.cxx index a8bcee69e8db1..f2d0f9a632d2b 100644 --- a/core/base/src/TDirectory.cxx +++ b/core/base/src/TDirectory.cxx @@ -164,7 +164,7 @@ TDirectory::TContext::~TContext() // Mask deprecation warnings to allow for deprecating the fgAddDirectory bit. #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable : C4996) +#pragma warning(disable : 4996) #else #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -207,8 +207,10 @@ void TDirectory::Append(TObject *obj, Bool_t replace /* = kFALSE */) if (replace && obj->GetName() && obj->GetName()[0]) { TObject *old; while (nullptr != (old = GetList()->FindObject(obj->GetName()))) { - Warning("Append","Replacing existing %s: %s (Potential memory leak).", - obj->IsA()->GetName(),obj->GetName()); + if (obj != old) { + Warning("Append", "Replacing existing %s: %s (Potential memory leak).", obj->IsA()->GetName(), + obj->GetName()); + } ROOT::DirAutoAdd_t func = old->IsA()->GetDirectoryAutoAdd(); if (func) { func(old,nullptr); diff --git a/core/base/src/TVirtualPadPainter.cxx b/core/base/src/TVirtualPadPainter.cxx index b8d5fe05fbe8a..5b78bee5d9655 100644 --- a/core/base/src/TVirtualPadPainter.cxx +++ b/core/base/src/TVirtualPadPainter.cxx @@ -11,6 +11,11 @@ #include "TVirtualPadPainter.h" #include "TPluginManager.h" +#include "TAttFill.h" +#include "TAttLine.h" +#include "TAttMarker.h" +#include "TAttText.h" +#include "TVirtualX.h" /** \class TVirtualPadPainter @@ -96,3 +101,113 @@ void TVirtualPadPainter::DrawTextUrl(Double_t x, Double_t y, const char *text, c { DrawText(x, y, text, kClear); } + +//////////////////////////////////////////////////////////////////////////////// +/// Set fill attributes + +void TVirtualPadPainter::SetAttFill(const TAttFill &att) +{ + SetFillColor(att.GetFillColor()); + SetFillStyle(att.GetFillStyle()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set line attributes + +void TVirtualPadPainter::SetAttLine(const TAttLine &att) +{ + SetLineColor(att.GetLineColor()); + SetLineStyle(att.GetLineStyle()); + SetLineWidth(att.GetLineWidth()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set marker attributes + +void TVirtualPadPainter::SetAttMarker(const TAttMarker &att) +{ + SetMarkerColor(att.GetMarkerColor()); + SetMarkerSize(att.GetMarkerSize()); + SetMarkerStyle(att.GetMarkerStyle()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set text attributes + +void TVirtualPadPainter::SetAttText(const TAttText &att) +{ + SetTextAlign(att.GetTextAlign()); + SetTextAngle(att.GetTextAngle()); + SetTextColor(att.GetTextColor()); + SetTextSize(att.GetTextSize()); + SetTextFont(att.GetTextFont()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get fill attributes + +const TAttFill &TVirtualPadPainter::GetAttFill() const +{ + static TAttFill att; + att.SetFillColor(GetFillColor()); + att.SetFillStyle(GetFillStyle()); + return att; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get line attributes + +const TAttLine &TVirtualPadPainter::GetAttLine() const +{ + static TAttLine att; + att.SetLineColor(GetLineColor()); + att.SetLineStyle(GetLineStyle()); + att.SetLineWidth(GetLineWidth()); + return att; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get marker attributes + +const TAttMarker &TVirtualPadPainter::GetAttMarker() const +{ + static TAttMarker att; + att.SetMarkerColor(GetMarkerColor()); + att.SetMarkerSize(GetMarkerSize()); + att.SetMarkerStyle(GetMarkerStyle()); + return att; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get text attributes + +const TAttText &TVirtualPadPainter::GetAttText() const +{ + static TAttText att; + att.SetTextAlign(GetTextAlign()); + att.SetTextAngle(GetTextAngle()); + att.SetTextColor(GetTextColor()); + att.SetTextSize(GetTextSize()); + att.SetTextFont(GetTextFont()); + return att; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set double buffer mode for specified device, redirect to gVirtualX + +void TVirtualPadPainter::SetDoubleBuffer(Int_t device, Int_t mode) +{ + // TODO: move to actual painter classes, call only for selected device + if (gVirtualX) + gVirtualX->SetDoubleBuffer(device, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set cursor for specified device, redirect to gVirtualX + +void TVirtualPadPainter::SetCursor(Int_t device, ECursor cursor) +{ + // TODO: move to actual painter classes, call only for selected device + if (gVirtualX) + gVirtualX->SetCursor(device, cursor); +} diff --git a/core/base/src/TVirtualX.cxx b/core/base/src/TVirtualX.cxx index 3de70acf015be..3c0f39558e328 100644 --- a/core/base/src/TVirtualX.cxx +++ b/core/base/src/TVirtualX.cxx @@ -378,6 +378,152 @@ void TVirtualX::DrawText(Int_t /*x*/, Int_t /*y*/, Float_t /*angle*/, { } +//////////////////////////////////////////////////////////////////////////////// +/// Get window drawing context +/// Should remain valid until window exists + +WinContext_t TVirtualX::GetWindowContext(Int_t /* wid */) +{ + return (WinContext_t) 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set fill attributes for specified window + +void TVirtualX::SetAttFill(WinContext_t /* wctxt */, const TAttFill &att) +{ + SetFillColor(att.GetFillColor()); + SetFillStyle(att.GetFillStyle()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set line attributes for specified window + +void TVirtualX::SetAttLine(WinContext_t /* wctxt */, const TAttLine &att) +{ + SetLineColor(att.GetLineColor()); + SetLineStyle(att.GetLineStyle()); + SetLineWidth(att.GetLineWidth()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set marker attributes for specified window + +void TVirtualX::SetAttMarker(WinContext_t /* wctxt */, const TAttMarker &att) +{ + SetMarkerColor(att.GetMarkerColor()); + SetMarkerSize(att.GetMarkerSize()); + SetMarkerStyle(att.GetMarkerStyle()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set text attributes for specified window + +void TVirtualX::SetAttText(WinContext_t /* wctxt */, const TAttText &att) +{ + SetTextAlign(att.GetTextAlign()); + SetTextAngle(att.GetTextAngle()); + SetTextColor(att.GetTextColor()); + SetTextSize(att.GetTextSize()); + SetTextFont(att.GetTextFont()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set window draw mode + +void TVirtualX::SetDrawModeW(WinContext_t /* wctxt */, EDrawMode mode) +{ + SetDrawMode(mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns window draw mode + +TVirtualX::EDrawMode TVirtualX::GetDrawModeW(WinContext_t /* wctxt */) +{ + return GetDrawMode(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Clear specified window + +void TVirtualX::ClearWindowW(WinContext_t /* wctxt */) +{ + ClearWindow(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Update specified window + +void TVirtualX::UpdateWindowW(WinContext_t /* wctxt */, Int_t mode) +{ + UpdateWindow(mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw box on specified window + +void TVirtualX::DrawBoxW(WinContext_t /* wctxt */, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) +{ + DrawBox(x1, y1, x2, y2, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw fill area on specified window + +void TVirtualX::DrawFillAreaW(WinContext_t /* wctxt */, Int_t n, TPoint *xy) +{ + DrawFillArea(n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw line on specified window + +void TVirtualX::DrawLineW(WinContext_t /* wctxt */, Int_t x1, Int_t y1, Int_t x2, Int_t y2) +{ + DrawLine(x1, y1, x2, y2); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw poly line on specified window + +void TVirtualX::DrawPolyLineW(WinContext_t /* wctxt */, Int_t n, TPoint *xy) +{ + DrawPolyLine(n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw line segments on specified window + +void TVirtualX::DrawLinesSegmentsW(WinContext_t /* wctxt */, Int_t n, TPoint *xy) +{ + DrawLinesSegments(n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw poly marker on specified window + +void TVirtualX::DrawPolyMarkerW(WinContext_t /* wctxt */, Int_t n, TPoint *xy) +{ + DrawPolyMarker(n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw text on specified window + +void TVirtualX::DrawTextW(WinContext_t /* wctxt */, Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) +{ + DrawText(x, y, angle, mgn, text, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw wtext on specified window + +void TVirtualX::DrawTextW(WinContext_t /* wctxt */, Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode) +{ + DrawText(x, y, angle, mgn, text, mode); +} + //////////////////////////////////////////////////////////////////////////////// /// Executes the command "code" coming from the other threads (Win32) diff --git a/core/clingutils/res/TClingUtils.h b/core/clingutils/res/TClingUtils.h index 650146571c703..37ede524c7920 100644 --- a/core/clingutils/res/TClingUtils.h +++ b/core/clingutils/res/TClingUtils.h @@ -203,6 +203,7 @@ class AnnotatedRecordDecl { bool fRequestOnlyTClass; int fRequestedVersionNumber; int fRequestedRNTupleSerializationMode; + std::string fRequestedRNTupleSoARecord; // clang-format on public: @@ -228,6 +229,7 @@ class AnnotatedRecordDecl { bool rRequestOnlyTClass, int rRequestedVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpret, const TNormalizedCtxt &normCtxt); @@ -240,6 +242,7 @@ class AnnotatedRecordDecl { bool rRequestOnlyTClass, int rRequestedVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpret, const TNormalizedCtxt &normCtxt); @@ -253,6 +256,7 @@ class AnnotatedRecordDecl { bool rRequestOnlyTClass, int rRequestedVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpret, const TNormalizedCtxt &normCtxt); @@ -267,6 +271,7 @@ class AnnotatedRecordDecl { bool rRequestOnlyTClass, int rRequestedVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpret, const TNormalizedCtxt &normCtxt); // clang-format on @@ -292,6 +297,7 @@ class AnnotatedRecordDecl { bool RequestOnlyTClass() const { return fRequestOnlyTClass; } int RequestedVersionNumber() const { return fRequestedVersionNumber; } int RequestedRNTupleSerializationMode() const { return fRequestedRNTupleSerializationMode; } + const std::string &RequestedRNTupleSoARecord() const { return fRequestedRNTupleSoARecord; } // clang-format on int RootFlag() const { // Return the request (streamerInfo, has_version, etc.) combined in a single diff --git a/core/clingutils/src/RStl.cxx b/core/clingutils/src/RStl.cxx index b14fe3f0ac440..7baad1ee29030 100644 --- a/core/clingutils/src/RStl.cxx +++ b/core/clingutils/src/RStl.cxx @@ -101,6 +101,7 @@ void ROOT::Internal::RStl::GenerateTClassFor(const clang::QualType &type, const false, -1, 0, + "", interp, normCtxt)); // clang-format on @@ -163,6 +164,7 @@ void ROOT::Internal::RStl::GenerateTClassFor(const char *requestedName, const cl false, -1, 0, + "", interp, normCtxt)); // clang-format on diff --git a/core/clingutils/src/TClingUtils.cxx b/core/clingutils/src/TClingUtils.cxx index ca92e458ffa34..1b0651c80350e 100644 --- a/core/clingutils/src/TClingUtils.cxx +++ b/core/clingutils/src/TClingUtils.cxx @@ -386,6 +386,7 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, bool rRequestOnlyTClass, int rRequestedVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt) : fRuleIndex(index), @@ -395,7 +396,8 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestedVersionNumber), - fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode) + fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode), + fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord) // clang-format on { TMetaUtils::GetNormalizedName(fNormalizedName, decl->getASTContext().getTypeDeclType(decl), interpreter,normCtxt); @@ -417,6 +419,7 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, bool rRequestOnlyTClass, int rRequestVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt) : fRuleIndex(index), @@ -427,7 +430,8 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber), - fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode) + fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode), + fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord) // clang-format on { // For comparison purposes. @@ -456,6 +460,7 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, bool rRequestOnlyTClass, int rRequestVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt) : fRuleIndex(index), @@ -466,7 +471,8 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber), - fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode) + fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode), + fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord) // clang-format on { // For comparison purposes. @@ -490,6 +496,7 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, bool rRequestOnlyTClass, int rRequestVersionNumber, int rRequestedRNTupleSerializationMode, + const std::string &rRequestedRNTupleSoARecord, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt) : fRuleIndex(index), @@ -500,7 +507,8 @@ AnnotatedRecordDecl::AnnotatedRecordDecl(long index, fRequestNoInputOperator(rRequestNoInputOperator), fRequestOnlyTClass(rRequestOnlyTClass), fRequestedVersionNumber(rRequestVersionNumber), - fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode) + fRequestedRNTupleSerializationMode(rRequestedRNTupleSerializationMode), + fRequestedRNTupleSoARecord(rRequestedRNTupleSoARecord) // clang-format on { // const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast (decl); @@ -1979,7 +1987,8 @@ void ROOT::TMetaUtils::WriteClassInit(std::ostream& finalString, if (HasCustomStreamerMemberFunction(cl, decl, interp, normCtxt)) { rootflag = rootflag | TClassTable__kHasCustomStreamerMember; } - finalString << "isa_proxy, " << rootflag << "," << "\n" << " sizeof(" << csymbol << ") );" << "\n"; + finalString << "isa_proxy, " << rootflag << "," << "\n" + << " sizeof(" << csymbol << "), alignof(" << csymbol << ") );" << "\n"; if (HasIOConstructor(decl, args, ctorTypes, interp)) { finalString << " instance.SetNew(&new_" << mappedname.c_str() << ");" << "\n"; if (args.size()==0 && NeedDestructor(decl, interp)) @@ -2041,6 +2050,11 @@ void ROOT::TMetaUtils::WriteClassInit(std::ostream& finalString, // FIXME Workaround: for the moment we do not generate coll proxies with unique ptrs since // they imply copies and therefore do not compile. auto classNameForIO = TClassEdit::GetNameForIO(classname); + + finalString << " static_assert(alignof(" << csymbol << "::value_type) <= 4096,\n"; + finalString << " \"Class with alignment strictly greater than 4096 are currently not supported in " + "CollectionProxy. \"\n"; + finalString << " \"Please report this case to the developers\");\n"; finalString << " instance.AdoptCollectionProxyInfo(TCollectionProxyInfo::Generate(TCollectionProxyInfo::" << methodTCP << "< " << classNameForIO.c_str() << " >()));" << "\n"; needCollectionProxy = true; @@ -2063,6 +2077,14 @@ void ROOT::TMetaUtils::WriteClassInit(std::ostream& finalString, } + //--------------------------------------------------------------------------- + // Register underlying SoA record for RNTuple SoA layouts + ///////////////////////////////////////////////////////////////////////////// + + if (!cl.RequestedRNTupleSoARecord().empty()) { + finalString << " instance.SetRNTupleSoARecord(\"" << cl.RequestedRNTupleSoARecord() << "\");" << "\n"; + } + //--------------------------------------------------------------------------- // Pass the schema evolution rules to TGenericClassInfo ///////////////////////////////////////////////////////////////////////////// diff --git a/core/cont/src/TObjectTable.cxx b/core/cont/src/TObjectTable.cxx index c16e481132dcf..da7942ae10f8c 100644 --- a/core/cont/src/TObjectTable.cxx +++ b/core/cont/src/TObjectTable.cxx @@ -50,7 +50,6 @@ via the command gObjectTable->Print() TContextMenu 3 3 48 144 144 TMethodArg 2166 2166 44 95304 95304 TPaveLabel 1 1 120 120 120 - THtml 1 1 32 32 32 TROOT 1 0 208 208 0 TApplication 1 1 28 28 28 TFileHandler 1 1 20 20 20 diff --git a/core/dictgen/res/ClassSelectionRule.h b/core/dictgen/res/ClassSelectionRule.h index b6c37b154bd15..0c42f1eac1c0a 100644 --- a/core/dictgen/res/ClassSelectionRule.h +++ b/core/dictgen/res/ClassSelectionRule.h @@ -47,6 +47,8 @@ class ClassSelectionRule final : public BaseSelectionRule int fRequestedVersionNumber; // Explicit request for a specific version number (default to no request with -1). // Explicit request for unsplit (-1) or split (=1), defaults to unset (=0) int fRequestedRNTupleSerializationMode = 0; + // If not empty, marks the class as an RNTuple SoA layout for the underlying given record class + std::string fRequestedRNTupleSoARecord; // clang-format on public: @@ -83,6 +85,7 @@ class ClassSelectionRule final : public BaseSelectionRule void SetRequestPrivate(bool val); void SetRequestedVersionNumber(int version); void SetRequestedRNTupleSerializationMode(int serializationMode); + void SetRequestedRNTupleSoARecord(const std::string &recordName); bool RequestOnlyTClass() const; // True if the user want the TClass intiliazer but *not* the interpreter meta data bool RequestNoStreamer() const; // Request no Streamer function in the dictionary @@ -92,6 +95,7 @@ class ClassSelectionRule final : public BaseSelectionRule bool RequestPrivate() const; int RequestedVersionNumber() const; int RequestedRNTupleSerializationMode() const; + const std::string &RequestedRNTupleSoARecord() const; }; #endif diff --git a/core/dictgen/src/ClassSelectionRule.cxx b/core/dictgen/src/ClassSelectionRule.cxx index fd0d7382c71ac..1d446c75efd9b 100644 --- a/core/dictgen/src/ClassSelectionRule.cxx +++ b/core/dictgen/src/ClassSelectionRule.cxx @@ -162,6 +162,11 @@ void ClassSelectionRule::SetRequestedRNTupleSerializationMode(int serializationM fRequestedRNTupleSerializationMode = serializationMode; } +void ClassSelectionRule::SetRequestedRNTupleSoARecord(const std::string &recordName) +{ + fRequestedRNTupleSoARecord = recordName; +} + bool ClassSelectionRule::RequestOnlyTClass() const { return fRequestOnlyTClass; @@ -186,3 +191,8 @@ int ClassSelectionRule::RequestedRNTupleSerializationMode() const { return fRequestedRNTupleSerializationMode; } + +const std::string &ClassSelectionRule::RequestedRNTupleSoARecord() const +{ + return fRequestedRNTupleSoARecord; +} diff --git a/core/dictgen/src/LinkdefReader.cxx b/core/dictgen/src/LinkdefReader.cxx index 0cb4ebdca6793..fe9a0fa01503a 100644 --- a/core/dictgen/src/LinkdefReader.cxx +++ b/core/dictgen/src/LinkdefReader.cxx @@ -27,6 +27,7 @@ #include #include +#include #include "LinkdefReader.h" #include "SelectionRules.h" #include "RConversionRuleParser.h" @@ -57,6 +58,7 @@ struct LinkdefReader::Options { }; int fVersionNumber; int fRNTupleSerializationMode; // 0: unset, -1: enforce streamed, 1: enforce native + std::string fRNTupleSoARecord; }; /* @@ -409,6 +411,7 @@ bool LinkdefReader::AddRule(const std::string& ruletype, if (options->fVersionNumber >= 0) csr.SetRequestedVersionNumber(options->fVersionNumber); if (options->fRNTupleSerializationMode != 0) csr.SetRequestedRNTupleSerializationMode(options->fRNTupleSerializationMode); + csr.SetRequestedRNTupleSoARecord(options->fRNTupleSoARecord); } if (csr.RequestStreamerInfo() && csr.RequestNoStreamer()) { std::cerr << "Warning: " << localIdentifier << " option + mutual exclusive with -, + prevails\n"; @@ -663,7 +666,8 @@ class LinkdefReaderPragmaHandler : public clang::PragmaHandler { * nomap: (ignored by roocling; prevents entry in ROOT's rootmap file) * stub: (ignored by rootcling was a directly for CINT code generation) * version(x): sets the version number of the class to x - * rntuple[un]split: enforce split/unsplit encoding in RNTuple + * rntupleStreamerMode(true|false): enforce/prevent use of the RNTuple streamer field + * rntupleSoARecord(x): marks the class as an RNTuple SoA layout for the underlying record class x */ // We assume that the first toke in option or options @@ -718,11 +722,36 @@ class LinkdefReaderPragmaHandler : public clang::PragmaHandler { "(either rntupleStreamerMode(true) or rntupleStreamerMode(false))", boolval, PP); } else { + if (!options.fRNTupleSoARecord.empty()) { + Error("Error: rntupleStreamerMode(true) and rntupleSoARecord are mutually exclusive", boolval, PP); + } options.fRNTupleSerializationMode = -1; } } else { Error("Error: Malformed rntupleStreamerMode option (either 'true' or 'false').", boolval, PP); } + } else if (tok.getIdentifierInfo()->getName() == "rntupleSoARecord") { + clang::Token start = tok; + PP.Lex(tok); + if (tok.isNot(clang::tok::l_paren)) { + Error("Error: missing left parenthesis after rntupleSoARecord.", start, PP); + return false; + } + PP.Lex(tok); + clang::Token strval = tok; + if (tok.isNot(clang::tok::eod)) + PP.Lex(tok); + if (tok.isNot(clang::tok::r_paren)) { + Error("Error: missing right parenthesis after rntupleSoARecord.", start, PP); + return false; + } + if (!strval.getIdentifierInfo() || strval.getIdentifierInfo()->getName().empty()) { + Error("Error: Malformed rntupleSoARecord option.", strval, PP); + } + if (options.fRNTupleSerializationMode == -1) { + Error("Error: rntupleStreamerMode(true) and rntupleSoARecord are mutually exclusive", strval, PP); + } + options.fRNTupleSoARecord = strval.getIdentifierInfo()->getName(); } else if (tok.getIdentifierInfo()->getName() == "stub") { // This was solely for CINT dictionary, ignore for now. // options.fUseStubs = 1; diff --git a/core/dictgen/src/Scanner.cxx b/core/dictgen/src/Scanner.cxx index 36e0a75802b31..facf26755cff4 100644 --- a/core/dictgen/src/Scanner.cxx +++ b/core/dictgen/src/Scanner.cxx @@ -563,6 +563,7 @@ int RScanner::AddAnnotatedRecordDecl(const ClassSelectionRule* selected, selected->RequestOnlyTClass(), selected->RequestedVersionNumber(), selected->RequestedRNTupleSerializationMode(), + selected->RequestedRNTupleSoARecord(), fInterpreter, fNormCtxt); } else { @@ -574,6 +575,7 @@ int RScanner::AddAnnotatedRecordDecl(const ClassSelectionRule* selected, selected->RequestOnlyTClass(), selected->RequestedVersionNumber(), selected->RequestedRNTupleSerializationMode(), + selected->RequestedRNTupleSoARecord(), fInterpreter, fNormCtxt); } diff --git a/core/dictgen/src/XMLReader.cxx b/core/dictgen/src/XMLReader.cxx index 50a546a520e7c..9d04f9d6a8c5a 100644 --- a/core/dictgen/src/XMLReader.cxx +++ b/core/dictgen/src/XMLReader.cxx @@ -961,6 +961,13 @@ bool XMLReader::Parse(const std::string &fileName, SelectionRules& out) "not both\n", lineNumCharp, iAttrValue.c_str()); } else { + if (!csr->RequestedRNTupleSoARecord().empty()) { + ROOT::TMetaUtils::Error( + nullptr, + "XML at line %s: class attributes rntupleStreamerMode and rntupleSoARecord " + "are mutually exclusive\n", + lineNumCharp, iAttrValue.c_str()); + } csr->SetRequestedRNTupleSerializationMode(-1); } } else { @@ -972,6 +979,18 @@ bool XMLReader::Parse(const std::string &fileName, SelectionRules& out) } } + // request RNTuple SoA record type name + if (tagKind == kClass && csr && "rntupleSoARecord" == iAttrName) { + if (csr->RequestedRNTupleSerializationMode() == -1) { + ROOT::TMetaUtils::Error( + nullptr, + "XML at line %s: class attributes rntupleStreamerMode and rntupleSoARecord " + "are mutually exclusive\n", + lineNumCharp, iAttrValue.c_str()); + } + csr->SetRequestedRNTupleSoARecord(iAttrValue); + } + // request no input operator if (tagKind == kClass && csr && "noInputOperator" == iAttrName){ if (iAttrValue == "true") { diff --git a/core/dictgen/src/rootcling_impl.cxx b/core/dictgen/src/rootcling_impl.cxx index 79707eb2d3901..4d2b03714a358 100644 --- a/core/dictgen/src/rootcling_impl.cxx +++ b/core/dictgen/src/rootcling_impl.cxx @@ -3930,7 +3930,7 @@ int RootClingMain(int argc, const char *etcDir = gDriverConfig->fTROOT__GetEtcDir(); std::string llvmResourceDir = etcDir ? std::string(etcDir) + "/cling" : ""; - + if (gBareClingSubcommand) { std::vector clingArgsC; clingArgsC.push_back(executableFileName); @@ -4106,7 +4106,7 @@ int RootClingMain(int argc, // cling-only arguments if (etcDir) clingArgs.push_back(std::string("-I") + llvm::sys::path::convert_to_slash(etcDir)); - + // We do not want __ROOTCLING__ in the pch! if (!gOptGeneratePCH) { clingArgs.push_back("-D__ROOTCLING__"); @@ -4616,7 +4616,7 @@ int RootClingMain(int argc, // interpPragmaSource and we still need to process it. LinkdefReader ldefr(interp, constructorTypes); - + if (!ldefr.Parse(selectionRules, interpPragmaSource, clingArgs, llvmResourceDir.c_str())) { ROOT::TMetaUtils::Error(nullptr, "Parsing #pragma failed %s\n", linkdefFilename.c_str()); @@ -5532,6 +5532,7 @@ int GenReflexMain(int argc, char **argv) " Default value is 'false'\n" " - rntupleStreamerMode [true/false]: enforce streamed or native writing for RNTuple.\n" " If unset, RNTuple stores classes in split mode or fails if the class cannot be split.\n" + " - rntupleSoARecord [class name]: marks the class as an RNTuple SoA layout for the underlying record\n" " - noInputOperator [true/false]: turns off input operator generation if set\n" " to 'true'. Default value is 'false'\n" " Example XML:\n" @@ -5542,6 +5543,7 @@ int GenReflexMain(int argc, char **argv) " [id=\"xxxx\"] [noStreamer=\"true/false\"]\n" " [noInputOperator=\"true/false\"]\n" " [rntupleStreamerMode=\"true/false\"] />\n" + " [rntupleSoARecord=\"class_name\"] />\n" " \n" " \n" " \n" diff --git a/core/foundation/CMakeLists.txt b/core/foundation/CMakeLists.txt index c2d8b61a40fc6..320a5db3bb2bf 100644 --- a/core/foundation/CMakeLists.txt +++ b/core/foundation/CMakeLists.txt @@ -14,6 +14,7 @@ set_property(TARGET Core APPEND PROPERTY DICT_HEADERS TClassEdit.h TError.h ThreadLocalStorage.h + ROOT/RAlignmentUtils.hxx ROOT/RError.hxx ROOT/RLogger.hxx ROOT/RNotFn.hxx diff --git a/core/foundation/inc/ROOT/RAlignmentUtils.hxx b/core/foundation/inc/ROOT/RAlignmentUtils.hxx new file mode 100644 index 0000000000000..422958d338793 --- /dev/null +++ b/core/foundation/inc/ROOT/RAlignmentUtils.hxx @@ -0,0 +1,41 @@ +// @(#)root/foundation: +// Author: Philippe Canal, April 2026 + +/************************************************************************* + * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_RAlignmentUtils +#define ROOT_RAlignmentUtils + +#include +#include + +namespace ROOT { +namespace Internal { + +/// Return true if \p align is a valid C++ alignment value: strictly positive +/// and a power of two. This is the set of values accepted by +/// `::operator new[](n, std::align_val_t(align))`. +inline constexpr bool IsValidAlignment(std::size_t align) noexcept +{ + return align > 0 && (align & (align - 1)) == 0; +} + +/// Round \p value up to the next multiple of \p align. +/// \p align must be a power of two (asserted at runtime in debug builds). +template +inline constexpr T AlignUp(T value, T align) noexcept +{ + assert(IsValidAlignment(static_cast(align))); // must be a power of two + return (value + align - 1) & ~(align - 1); +} + +} // namespace Internal +} // namespace ROOT + +#endif // ROOT_RAlignmentUtils diff --git a/core/gui/inc/GuiTypes.h b/core/gui/inc/GuiTypes.h index 41052a7a403de..ac522ea3702eb 100644 --- a/core/gui/inc/GuiTypes.h +++ b/core/gui/inc/GuiTypes.h @@ -27,6 +27,7 @@ typedef ULongptr_t Handle_t; ///< Generic resource handle typedef Handle_t Display_t; ///< Display handle typedef Handle_t Visual_t; ///< Visual handle typedef Handle_t Window_t; ///< Window handle +typedef Handle_t WinContext_t; ///< Window drawing context typedef Handle_t Pixmap_t; ///< Pixmap handle typedef Handle_t Drawable_t; ///< Drawable handle typedef Handle_t Region_t; ///< Region handle diff --git a/core/gui/inc/TCanvasImp.h b/core/gui/inc/TCanvasImp.h index 0d8f3205677a3..a411436451770 100644 --- a/core/gui/inc/TCanvasImp.h +++ b/core/gui/inc/TCanvasImp.h @@ -64,7 +64,8 @@ friend class TCanvas; w = h = 0; return 0; } - virtual void Iconify() {} + + virtual void Iconify() {} virtual Int_t InitWindow() { return 0; } virtual void SetStatusText(const char *text = nullptr, Int_t partidx = 0) { (void) text; (void) partidx; } virtual void SetWindowPosition(Int_t x, Int_t y) { (void) x; (void) y; } @@ -87,6 +88,12 @@ friend class TCanvas; virtual Bool_t HasToolBar() const { return kFALSE; } virtual Bool_t HasToolTips() const { return kFALSE; } + virtual void Warp(Int_t ix, Int_t iy); + virtual Int_t RequestLocator(Int_t &x, Int_t &y); + virtual void GetCanvasGeometry(Int_t wid, UInt_t &w, UInt_t &h); + virtual void ResizeCanvasWindow(Int_t wid); + virtual void UpdateDisplay(Int_t mode = 0, Bool_t sleep = kFALSE); + ClassDef(TCanvasImp,0) //ABC describing main window protocol }; diff --git a/core/gui/src/TCanvasImp.cxx b/core/gui/src/TCanvasImp.cxx index 639f34c50cb83..b43a721f6222d 100644 --- a/core/gui/src/TCanvasImp.cxx +++ b/core/gui/src/TCanvasImp.cxx @@ -17,4 +17,52 @@ and a drawing area). */ #include "TCanvasImp.h" +#include "TVirtualX.h" +#include "TSystem.h" + +//////////////////////////////////////////////////////////////////////////////// +/// Change mouse pointer, redirect to gVirtualX + +void TCanvasImp::Warp(Int_t ix, Int_t iy) +{ + if(gVirtualX) + gVirtualX->Warp(ix, iy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Request current mouse pointer, redirect to gVirtualX + +Int_t TCanvasImp::RequestLocator(Int_t &x, Int_t &y) +{ + return gVirtualX ? gVirtualX->RequestLocator(1, 1, x, y) : -1; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Gets the size and position of the canvas paint area. + +void TCanvasImp::GetCanvasGeometry(Int_t wid, UInt_t &w, UInt_t &h) +{ + Int_t x, y; + gVirtualX->GetGeometry(wid, x, y, w, h); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Resize canvas window, redirect to gVirtualX + +void TCanvasImp::ResizeCanvasWindow(Int_t wid) +{ + if (gVirtualX) + gVirtualX->ResizeWindow(wid); //resize canvas and off-screen buffer +} + +//////////////////////////////////////////////////////////////////////////////// +/// Update gVirtualX display, also optionally sleep to wait until operation finished + +void TCanvasImp::UpdateDisplay(Int_t mode, Bool_t sleep) +{ + if (gVirtualX) + gVirtualX->Update(mode); + if (sleep) + gSystem->Sleep(30); +} diff --git a/core/lz4/CMakeLists.txt b/core/lz4/CMakeLists.txt index 06a709db8bd0b..e9f142aa4033f 100644 --- a/core/lz4/CMakeLists.txt +++ b/core/lz4/CMakeLists.txt @@ -4,13 +4,8 @@ # For the licensing terms see $ROOTSYS/LICENSE. # For the list of contributors see $ROOTSYS/README/CREDITS. -find_package(LZ4 REQUIRED) find_package(xxHash REQUIRED) -if(builtin_lz4) - add_dependencies(Core BUILTIN_LZ4) -endif() - target_sources(Core PRIVATE src/ZipLZ4.cxx) target_link_libraries(Core PRIVATE xxHash::xxHash LZ4::LZ4) target_include_directories(Core PUBLIC diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h index d1e298cddcbe9..fec709736ea2b 100644 --- a/core/meta/inc/TClass.h +++ b/core/meta/inc/TClass.h @@ -248,6 +248,7 @@ friend class TStreamerInfo; //Wrapper around this class custom conversion Streamer member function. ClassConvStreamerFunc_t fConvStreamerFunc = nullptr; Int_t fSizeof = -1; //Sizeof the class. + std::size_t fAlignment = 0; //Alignment of the class (0 for unknown alignment) std::atomic fCanSplit = -1; /// enum EDataType { kChar_t = 1, kUChar_t = 11, kShort_t = 2, kUShort_t = 12, @@ -45,7 +45,8 @@ class TDataType : public TDictionary { private: TypedefInfo_t *fInfo; /// fReadRules; @@ -76,17 +78,13 @@ namespace ROOT { std::unordered_map fAdoptedMemberStreamers; public: - TGenericClassInfo(const char *fullClassname, - const char *declFileName, Int_t declFileLine, - const std::type_info &info, const Internal::TInitBehavior *action, - DictFuncPtr_t dictionary, - TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof); + TGenericClassInfo(const char *fullClassname, const char *declFileName, Int_t declFileLine, + const std::type_info &info, const Internal::TInitBehavior *action, DictFuncPtr_t dictionary, + TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_ = 0); - TGenericClassInfo(const char *fullClassname, Int_t version, - const char *declFileName, Int_t declFileLine, - const std::type_info &info, const Internal::TInitBehavior *action, - DictFuncPtr_t dictionary, - TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof); + TGenericClassInfo(const char *fullClassname, Int_t version, const char *declFileName, Int_t declFileLine, + const std::type_info &info, const Internal::TInitBehavior *action, DictFuncPtr_t dictionary, + TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_ = 0); TGenericClassInfo(const char *fullClassname, Int_t version, const char *declFileName, Int_t declFileLine, @@ -142,6 +140,7 @@ namespace ROOT { void SetStreamerFunc(ClassStreamerFunc_t); void SetConvStreamerFunc(ClassConvStreamerFunc_t); Short_t SetVersion(Short_t version); + void SetRNTupleSoARecord(const std::string &recordName); // protected: private: diff --git a/core/meta/inc/TInterpreter.h b/core/meta/inc/TInterpreter.h index 94980fdb0a7fc..436406f72eaf1 100644 --- a/core/meta/inc/TInterpreter.h +++ b/core/meta/inc/TInterpreter.h @@ -430,6 +430,7 @@ class TInterpreter : public TNamed { virtual void *ClassInfo_New(ClassInfo_t * /* info */, void * /* arena */) const {return nullptr;} virtual Long_t ClassInfo_Property(ClassInfo_t * /* info */) const {return 0;} virtual int ClassInfo_Size(ClassInfo_t * /* info */) const {return 0;} + virtual size_t ClassInfo_AlignOf(ClassInfo_t * /* info */) const {return 0;} virtual Longptr_t ClassInfo_Tagnum(ClassInfo_t * /* info */) const {return 0;} virtual const char *ClassInfo_FileName(ClassInfo_t * /* info */) const {return nullptr;} virtual const char *ClassInfo_FullName(ClassInfo_t * /* info */) const {return nullptr;} diff --git a/core/meta/inc/TStreamerElement.h b/core/meta/inc/TStreamerElement.h index 90363ecc9eec2..840ab8842b279 100644 --- a/core/meta/inc/TStreamerElement.h +++ b/core/meta/inc/TStreamerElement.h @@ -101,6 +101,7 @@ class TStreamerElement : public TNamed { Int_t GetArrayLength() const {return fArrayLength;} virtual TClass *GetClassPointer() const; TClass *GetClass() const {return GetClassPointer();} + virtual std::size_t GetAlignment() const; virtual Int_t GetExecID() const; virtual const char *GetFullName() const; virtual const char *GetInclude() const {return "";} @@ -172,6 +173,7 @@ class TStreamerBase : public TStreamerElement { const char *GetInclude() const override; TClass *GetNewBaseClass() { return fNewBaseClass; } ULongptr_t GetMethod() const override {return 0;} + std::size_t GetAlignment() const override; Int_t GetSize() const override; TVirtualStreamerInfo *GetBaseStreamerInfo() const { return fStreamerInfo; } void Init(TVirtualStreamerInfo *obj = nullptr) override; @@ -213,6 +215,7 @@ class TStreamerBasicPointer : public TStreamerElement { const char *GetCountName() const {return fCountName.Data();} Int_t GetCountVersion() const {return fCountVersion;} ULongptr_t GetMethod() const override; + std::size_t GetAlignment() const override { return alignof(void *); } Int_t GetSize() const override; void Init(TVirtualStreamerInfo *obj = nullptr) override; Bool_t HasCounter() const override { return fCounter != nullptr; } @@ -249,6 +252,7 @@ class TStreamerLoop : public TStreamerElement { Int_t GetCountVersion() const {return fCountVersion;} const char *GetInclude() const override; ULongptr_t GetMethod() const override; + std::size_t GetAlignment() const override; Int_t GetSize() const override; void Init(TVirtualStreamerInfo *obj = nullptr) override; Bool_t IsaPointer() const override {return kTRUE; } @@ -297,6 +301,7 @@ class TStreamerObject : public TStreamerElement { TStreamerObject(const char *name, const char *title, Int_t offset, const char *typeName); virtual ~TStreamerObject(); const char *GetInclude() const override; + std::size_t GetAlignment() const override; Int_t GetSize() const override; void Init(TVirtualStreamerInfo *obj = nullptr) override; @@ -316,6 +321,7 @@ class TStreamerObjectAny : public TStreamerElement { TStreamerObjectAny(const char *name, const char *title, Int_t offset, const char *typeName); virtual ~TStreamerObjectAny(); const char *GetInclude() const override; + std::size_t GetAlignment() const override; Int_t GetSize() const override; void Init(TVirtualStreamerInfo *obj = nullptr) override; @@ -335,6 +341,7 @@ class TStreamerObjectPointer : public TStreamerElement { TStreamerObjectPointer(const char *name, const char *title, Int_t offset, const char *typeName); virtual ~TStreamerObjectPointer(); const char *GetInclude() const override; + std::size_t GetAlignment() const override { return alignof(void *); } Int_t GetSize() const override; void Init(TVirtualStreamerInfo *obj = nullptr) override; Bool_t IsaPointer() const override {return kTRUE;} @@ -356,6 +363,7 @@ class TStreamerObjectAnyPointer : public TStreamerElement { TStreamerObjectAnyPointer(const char *name, const char *title, Int_t offset, const char *typeName); virtual ~TStreamerObjectAnyPointer(); const char *GetInclude() const override; + std::size_t GetAlignment() const override { return alignof(void *); } Int_t GetSize() const override; void Init(TVirtualStreamerInfo *obj = nullptr) override; Bool_t IsaPointer() const override { return kTRUE; } @@ -377,6 +385,7 @@ class TStreamerString : public TStreamerElement { TStreamerString(const char *name, const char *title, Int_t offset); virtual ~TStreamerString(); const char *GetInclude() const override; + std::size_t GetAlignment() const override { return alignof(TString); } Int_t GetSize() const override; ClassDefOverride(TStreamerString,2) //Streamer element of type TString @@ -408,6 +417,7 @@ class TStreamerSTL : public TStreamerElement { Int_t GetSTLtype() const {return fSTLtype;} Int_t GetCtype() const {return fCtype;} const char *GetInclude() const override; + std::size_t GetAlignment() const override; Int_t GetSize() const override; void ls(Option_t *option="") const override; void SetSTLtype(Int_t t) {fSTLtype = t;} diff --git a/core/meta/inc/TVirtualStreamerInfo.h b/core/meta/inc/TVirtualStreamerInfo.h index 24144d85aecfa..9c227e39a0489 100644 --- a/core/meta/inc/TVirtualStreamerInfo.h +++ b/core/meta/inc/TVirtualStreamerInfo.h @@ -177,6 +177,7 @@ class TVirtualStreamerInfo : public TNamed { TVirtualStreamerInfo(); TVirtualStreamerInfo(TClass * /*cl*/); virtual ~TVirtualStreamerInfo(); + virtual size_t GetClassAlignment() const = 0; virtual void Build(Bool_t isTransient = kFALSE) = 0; virtual void BuildCheck(TFile *file = nullptr, Bool_t load = kTRUE) = 0; virtual void BuildEmulated(TFile *file) = 0; diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx index 137f09b0bcd8c..6c6b13cbdae1d 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -124,6 +124,7 @@ In order to access the name of a class within the ROOT type system, the method T #include "TClonesArray.h" #include "TRef.h" #include "TRefArray.h" +#include "ROOT/RAlignmentUtils.hxx" using std::multimap, std::make_pair, std::string; @@ -2735,6 +2736,13 @@ Int_t TClass::GetBaseClassOffsetRecurse(const TClass *cl) if (!baseclass) return -1; Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl); if (subOffset == -2) return -2; + auto align = baseclass->GetClassAlignment(); + if (ROOT::Internal::IsValidAlignment(align)) { + offset = ROOT::Internal::AlignUp((size_t)offset, align); + } else { + Error("GetBaseClassOffsetRecurse", "Can not determine alignment for base class %s (got %zu)\n", + baseclass->GetName(), align); + } if (subOffset != -1) return offset+subOffset; offset += baseclass->Size(); } else if (element->IsA() == TStreamerSTL::Class()) { @@ -2743,6 +2751,13 @@ Int_t TClass::GetBaseClassOffsetRecurse(const TClass *cl) if (!baseclass) return -1; Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl); if (subOffset == -2) return -2; + auto align = baseclass->GetClassAlignment(); + if (ROOT::Internal::IsValidAlignment(align)) { + offset = ROOT::Internal::AlignUp((size_t)offset, align); + } else { + Error("GetBaseClassOffsetRecurse", "Can not determine alignment for base class %s (got %zu)\n", + baseclass->GetName(), align); + } if (subOffset != -1) return offset+subOffset; offset += baseclass->Size(); @@ -5753,6 +5768,38 @@ void TClass::SetCurrentStreamerInfo(TVirtualStreamerInfo *info) fCurrentInfo = info; } +//////////////////////////////////////////////////////////////////////////////// +/// Return the alignment requirement (in bytes) for objects of this class. +/// +/// Returns (size_t)-1 if the class info is invalid, 0 for a forward-declared +/// class, an enum, a namespace or or a class with no definition. For all other +/// cases the actual alignment obtained from the dictionary or the clang ASTRecordLayout, +/// or the StreamerInfo (in that order of priority) is returned. +/// +/// Returns `0` when the alignment cannot be determined. + +size_t TClass::GetClassAlignment() const +{ + if (fAlignment != 0) + return fAlignment; + if ((fState < kEmulated && !fCollectionProxy) || Property() & (kIsNamespace | kIsEnum)) + return 0; + if (HasInterpreterInfo()) { + return gCling->ClassInfo_AlignOf(GetClassInfo()); + } + if (fCollectionProxy) { + // If the collection proxy has a dictionary, it will have return earlier, + // so we know that the collection proxy is emulated. + if (!(fCollectionProxy->GetProperties() & TVirtualCollectionProxy::kIsEmulated)) { + Fatal("TClass::GetClassAlignment", "Cannot determine alignment for collection proxy of class %s.", GetName()); + return 0; + } + return alignof(std::vector); + } + assert(GetStreamerInfo() && GetStreamerInfo()->GetClassAlignment() != 0); + return GetStreamerInfo()->GetClassAlignment(); +} + //////////////////////////////////////////////////////////////////////////////// /// Return size of object of this class. diff --git a/core/meta/src/TDataType.cxx b/core/meta/src/TDataType.cxx index 6215649b262f6..ab469b4f6b49c 100644 --- a/core/meta/src/TDataType.cxx +++ b/core/meta/src/TDataType.cxx @@ -41,6 +41,7 @@ TDataType::TDataType(TypedefInfo_t *info) : TDictionary(), R__LOCKGUARD(gInterpreterMutex); SetName(gCling->TypedefInfo_Name(fInfo)); SetTitle(gCling->TypedefInfo_Title(fInfo)); + // SetType sets fTrueName, fType , fSize and fAlignOf. SetType(gCling->TypedefInfo_TrueName(fInfo)); fProperty = gCling->TypedefInfo_Property(fInfo); fSize = gCling->TypedefInfo_Size(fInfo); @@ -48,6 +49,7 @@ TDataType::TDataType(TypedefInfo_t *info) : TDictionary(), SetTitle("Builtin basic type"); fProperty = 0; fSize = 0; + fAlignOf = 0; fType = kNoType_t; } } @@ -68,14 +70,16 @@ TDataType::TDataType(const char *typenam) : fInfo(nullptr), fProperty(kIsFundame //////////////////////////////////////////////////////////////////////////////// ///copy constructor -TDataType::TDataType(const TDataType& dt) : - TDictionary(dt), - fInfo(gCling->TypedefInfo_FactoryCopy(dt.fInfo)), - fSize(dt.fSize), - fType(dt.fType), - fProperty(dt.fProperty), - fTrueName(dt.fTrueName), - fTypeNameIdx(dt.fTypeNameIdx), fTypeNameLen(dt.fTypeNameLen) +TDataType::TDataType(const TDataType &dt) + : TDictionary(dt), + fInfo(gCling->TypedefInfo_FactoryCopy(dt.fInfo)), + fSize(dt.fSize), + fAlignOf(dt.fAlignOf), + fType(dt.fType), + fProperty(dt.fProperty), + fTrueName(dt.fTrueName), + fTypeNameIdx(dt.fTypeNameIdx), + fTypeNameLen(dt.fTypeNameLen) { } @@ -89,6 +93,7 @@ TDataType& TDataType::operator=(const TDataType& dt) gCling->TypedefInfo_Delete(fInfo); fInfo=gCling->TypedefInfo_FactoryCopy(dt.fInfo); fSize=dt.fSize; + fAlignOf=dt.fAlignOf; fType=dt.fType; fProperty=dt.fProperty; fTrueName=dt.fTrueName; @@ -301,69 +306,89 @@ void TDataType::SetType(const char *name) fTrueName = name; fType = kOther_t; fSize = 0; + fAlignOf = 0; if (name==nullptr) { return; } else if (!strcmp("unsigned int", name)) { fType = kUInt_t; fSize = sizeof(UInt_t); + fAlignOf = alignof(UInt_t); } else if (!strcmp("unsigned", name)) { fType = kUInt_t; fSize = sizeof(UInt_t); + fAlignOf = alignof(UInt_t); } else if (!strcmp("int", name)) { fType = kInt_t; fSize = sizeof(Int_t); + fAlignOf = alignof(Int_t); } else if (!strcmp("unsigned long", name)) { fType = kULong_t; fSize = sizeof(ULong_t); + fAlignOf = alignof(ULong_t); } else if (!strcmp("long", name)) { fType = kLong_t; fSize = sizeof(Long_t); + fAlignOf = alignof(Long_t); } else if (!strcmp("unsigned long long", name) || !strcmp("ULong64_t",name)) { fType = kULong64_t; fSize = sizeof(ULong64_t); + fAlignOf = alignof(ULong64_t); } else if (!strcmp("long long", name) || !strcmp("Long64_t",name)) { fType = kLong64_t; fSize = sizeof(Long64_t); + fAlignOf = alignof(Long64_t); } else if (!strcmp("unsigned short", name)) { fType = kUShort_t; fSize = sizeof(UShort_t); + fAlignOf = alignof(UShort_t); } else if (!strcmp("short", name)) { fType = kShort_t; fSize = sizeof(Short_t); + fAlignOf = alignof(Short_t); } else if (!strcmp("unsigned char", name)) { fType = kUChar_t; fSize = sizeof(UChar_t); + fAlignOf = alignof(UChar_t); } else if (!strcmp("char", name)) { fType = kChar_t; fSize = sizeof(Char_t); + fAlignOf = alignof(Char_t); } else if (!strcmp("bool", name)) { fType = kBool_t; fSize = sizeof(Bool_t); + fAlignOf = alignof(Bool_t); } else if (!strcmp("float", name)) { fType = kFloat_t; fSize = sizeof(Float_t); + fAlignOf = alignof(Float_t); } else if (!strcmp("double", name)) { fType = kDouble_t; fSize = sizeof(Double_t); + fAlignOf = alignof(Double_t); } else if (!strcmp("signed char", name)) { fType = kChar_t; // kDataTypeAliasSignedChar_t; fSize = sizeof(Char_t); + fAlignOf = alignof(Char_t); } else if (!strcmp("void", name)) { fType = kVoid_t; fSize = 0; + fAlignOf = 0; } if (!strcmp("Float16_t", fName.Data())) { fSize = sizeof(Float16_t); + fAlignOf = alignof(Float16_t); fType = kFloat16_t; } if (!strcmp("Double32_t", fName.Data())) { fSize = sizeof(Double32_t); + fAlignOf = alignof(Double32_t); fType = kDouble32_t; } if (!strcmp("char*",fName.Data())) { fType = kCharStar; + fAlignOf = alignof(char *); } // kCounter = 6, kBits = 15 } diff --git a/core/meta/src/TGenericClassInfo.cxx b/core/meta/src/TGenericClassInfo.cxx index c406b977a212e..b0dd17db3fd4e 100644 --- a/core/meta/src/TGenericClassInfo.cxx +++ b/core/meta/src/TGenericClassInfo.cxx @@ -82,63 +82,116 @@ namespace Internal { } } // Internal +TGenericClassInfo::TGenericClassInfo(const char *fullClassname, const char *declFileName, Int_t declFileLine, + const std::type_info &info, const Internal::TInitBehavior *action, + DictFuncPtr_t dictionary, TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, + std::size_t alignof_) + : fAction(action), + fClass(nullptr), + fClassName(fullClassname), + fDeclFileName(declFileName), + fDeclFileLine(declFileLine), + fDictionary(dictionary), + fInfo(info), + fImplFileName(nullptr), + fImplFileLine(0), + fIsA(isa), + fVersion(1), + fMerge(nullptr), + fResetAfterMerge(nullptr), + fNew(nullptr), + fNewArray(nullptr), + fDelete(nullptr), + fDeleteArray(nullptr), + fDestructor(nullptr), + fDirAutoAdd(nullptr), + fStreamer(nullptr), + fStreamerFunc(nullptr), + fConvStreamerFunc(nullptr), + fCollectionProxy(nullptr), + fSizeof(sizof), + fAlignment(alignof_), + fPragmaBits(pragmabits), + fCollectionProxyInfo(nullptr), + fCollectionStreamerInfo(nullptr) +{ + // Constructor. + + Init(pragmabits); +} - TGenericClassInfo::TGenericClassInfo(const char *fullClassname, - const char *declFileName, Int_t declFileLine, - const std::type_info &info, const Internal::TInitBehavior *action, - DictFuncPtr_t dictionary, - TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof) - : fAction(action), fClass(nullptr), fClassName(fullClassname), - fDeclFileName(declFileName), fDeclFileLine(declFileLine), - fDictionary(dictionary), fInfo(info), - fImplFileName(nullptr), fImplFileLine(0), - fIsA(isa), - fVersion(1), - fMerge(nullptr),fResetAfterMerge(nullptr),fNew(nullptr),fNewArray(nullptr),fDelete(nullptr),fDeleteArray(nullptr),fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamer(nullptr), - fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(sizof), fPragmaBits(pragmabits), - fCollectionProxyInfo(nullptr), fCollectionStreamerInfo(nullptr) - { - // Constructor. - - Init(pragmabits); - } - - TGenericClassInfo::TGenericClassInfo(const char *fullClassname, Int_t version, - const char *declFileName, Int_t declFileLine, - const std::type_info &info, const Internal::TInitBehavior *action, - DictFuncPtr_t dictionary, - TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof) - : fAction(action), fClass(nullptr), fClassName(fullClassname), - fDeclFileName(declFileName), fDeclFileLine(declFileLine), - fDictionary(dictionary), fInfo(info), - fImplFileName(nullptr), fImplFileLine(0), - fIsA(isa), - fVersion(version), - fMerge(nullptr),fResetAfterMerge(nullptr),fNew(nullptr),fNewArray(nullptr),fDelete(nullptr),fDeleteArray(nullptr),fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamer(nullptr), - fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(sizof), fPragmaBits(pragmabits), - fCollectionProxyInfo(nullptr), fCollectionStreamerInfo(nullptr) - - { - // Constructor with version number and no showmembers. - - Init(pragmabits); - } +TGenericClassInfo::TGenericClassInfo(const char *fullClassname, Int_t version, const char *declFileName, + Int_t declFileLine, const std::type_info &info, + const Internal::TInitBehavior *action, DictFuncPtr_t dictionary, + TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof, std::size_t alignof_) + : fAction(action), + fClass(nullptr), + fClassName(fullClassname), + fDeclFileName(declFileName), + fDeclFileLine(declFileLine), + fDictionary(dictionary), + fInfo(info), + fImplFileName(nullptr), + fImplFileLine(0), + fIsA(isa), + fVersion(version), + fMerge(nullptr), + fResetAfterMerge(nullptr), + fNew(nullptr), + fNewArray(nullptr), + fDelete(nullptr), + fDeleteArray(nullptr), + fDestructor(nullptr), + fDirAutoAdd(nullptr), + fStreamer(nullptr), + fStreamerFunc(nullptr), + fConvStreamerFunc(nullptr), + fCollectionProxy(nullptr), + fSizeof(sizof), + fAlignment(alignof_), + fPragmaBits(pragmabits), + fCollectionProxyInfo(nullptr), + fCollectionStreamerInfo(nullptr) + +{ + // Constructor with version number and no showmembers. + + Init(pragmabits); +} class TForNamespace {}; // Dummy class to give a typeid to namespace (See also TClassTable.cc) - TGenericClassInfo::TGenericClassInfo(const char *fullClassname, Int_t version, - const char *declFileName, Int_t declFileLine, - const Internal::TInitBehavior *action, + TGenericClassInfo::TGenericClassInfo(const char *fullClassname, Int_t version, const char *declFileName, + Int_t declFileLine, const Internal::TInitBehavior *action, DictFuncPtr_t dictionary, Int_t pragmabits) - : fAction(action), fClass(nullptr), fClassName(fullClassname), - fDeclFileName(declFileName), fDeclFileLine(declFileLine), - fDictionary(dictionary), fInfo(typeid(TForNamespace)), - fImplFileName(nullptr), fImplFileLine(0), + : fAction(action), + fClass(nullptr), + fClassName(fullClassname), + fDeclFileName(declFileName), + fDeclFileLine(declFileLine), + fDictionary(dictionary), + fInfo(typeid(TForNamespace)), + fImplFileName(nullptr), + fImplFileLine(0), fIsA(nullptr), fVersion(version), - fMerge(nullptr),fResetAfterMerge(nullptr),fNew(nullptr),fNewArray(nullptr),fDelete(nullptr),fDeleteArray(nullptr),fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamer(nullptr), - fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fCollectionProxy(nullptr), fSizeof(0), fPragmaBits(pragmabits), - fCollectionProxyInfo(nullptr), fCollectionStreamerInfo(nullptr) + fMerge(nullptr), + fResetAfterMerge(nullptr), + fNew(nullptr), + fNewArray(nullptr), + fDelete(nullptr), + fDeleteArray(nullptr), + fDestructor(nullptr), + fDirAutoAdd(nullptr), + fStreamer(nullptr), + fStreamerFunc(nullptr), + fConvStreamerFunc(nullptr), + fCollectionProxy(nullptr), + fSizeof(0), + fAlignment(0), + fPragmaBits(pragmabits), + fCollectionProxyInfo(nullptr), + fCollectionStreamerInfo(nullptr) { // Constructor for namespace @@ -295,6 +348,7 @@ namespace Internal { } } fClass->SetClassSize(fSizeof); + fClass->SetClassAlignment(fAlignment); //--------------------------------------------------------------------- // Attach the schema evolution information @@ -314,6 +368,11 @@ namespace Internal { fClass->GetAttributeMap()->AddProperty("rntuple.streamerMode", "true"); } } + + if (!fRNTupleSoARecord.empty()) { + fClass->CreateAttributeMap(); + fClass->GetAttributeMap()->AddProperty("rntuple.SoARecord", fRNTupleSoARecord.c_str()); + } } return fClass; } @@ -433,6 +492,11 @@ namespace Internal { return version; } + void TGenericClassInfo::SetRNTupleSoARecord(const std::string &recordName) + { + fRNTupleSoARecord = recordName; + } + void TGenericClassInfo::AdoptAlternate(ROOT::TClassAlt *alt) { fAlternate.push_back(alt); diff --git a/core/meta/src/TStreamerElement.cxx b/core/meta/src/TStreamerElement.cxx index 561fca629178d..305485e512748 100644 --- a/core/meta/src/TStreamerElement.cxx +++ b/core/meta/src/TStreamerElement.cxx @@ -20,6 +20,7 @@ #include "TBaseClass.h" #include "TDataMember.h" #include "TDataType.h" +#include "ROOT/RAlignmentUtils.hxx" #include "TEnum.h" #include "TRealData.h" #include "ThreadLocalStorage.h" @@ -307,7 +308,17 @@ Int_t TStreamerElement::GetExecID() const // inheriting from it (see ROOT-7052) const TString clName = ExtractClassName(fTypeName); const auto cl = TClass::GetClass(clName, kFALSE, kTRUE); - if (!cl || (nullptr == cl->GetBaseClass("TRef") && nullptr == cl->GetBaseClass("TRefArray"))) + // FIXME: The check for HasDataMemberInfo() is likely wrong because it could miss inheritance (chains) from TRef. + // However, it is needed to protect against non-loaded classes, previously also present in TClass::GetBaseClass. + if (!cl || !cl->HasDataMemberInfo()) + return 0; + // Classes cannot both inherit from TRef/TRefArray and have a collection proxy. + if (cl->GetCollectionProxy()) + return 0; + // Only classes inheriting from TObject can inherit from TRef. Do not look inside other classes. + if (!cl->IsTObject()) + return 0; + if (!cl->InheritsFrom("TRef") && !cl->InheritsFrom("TRefArray")) return 0; } @@ -379,6 +390,24 @@ Int_t TStreamerElement::GetSize() const return fSize; } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the alignment of this element in bytes. +/// The bare underlying type (stripping kOffsetL / kOffsetP array/pointer markers) +/// is used to determine the alignment from TDataType. + +std::size_t TStreamerElement::GetAlignment() const +{ + // Strip kOffsetL / kOffsetP markers to recover the bare type id. + const EDataType bareType = (EDataType)(fType % TVirtualStreamerInfo::kOffsetL); + if (bareType == kCounter || bareType == kBits) + return sizeof(UInt_t); + if (auto *dt = TDataType::GetDataType(bareType); dt && dt->GetAlignOf()) + return dt->GetAlignOf(); + Error("TStreamerElement::GetAlignment", "Cannot determine alignment for type %d (bare type %d) for element %s", + fType, bareType, GetName()); + return alignof(std::max_align_t); +} + //////////////////////////////////////////////////////////////////////////////// /// Return the local streamer object. @@ -683,6 +712,21 @@ Int_t TStreamerBase::GetSize() const return 0; } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the alignment of the base class in bytes. + +std::size_t TStreamerBase::GetAlignment() const +{ + TClass *cl = GetNewClass(); + if (!cl) + cl = GetClassPointer(); + if (cl && cl->GetClassAlignment()) + return cl->GetClassAlignment(); + // The caller will complains if the missing alignment information + // causes a problem. + return 0; +} + //////////////////////////////////////////////////////////////////////////////// /// Setup the element. @@ -1045,6 +1089,24 @@ TStreamerLoop::~TStreamerLoop() { } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the alignment of this element in bytes. +/// The bare underlying type (stripping kOffsetL / kOffsetP array/pointer markers) +/// is used to determine the alignment from TDataType. + +std::size_t TStreamerLoop::GetAlignment() const +{ + // Strip kOffsetL / kOffsetP markers to recover the bare type id. + const EDataType bareType = (EDataType)(fType % TVirtualStreamerInfo::kOffsetL); + if (bareType == kCounter || bareType == kBits) + return sizeof(UInt_t); + if (auto *dt = TDataType::GetDataType(bareType); dt && dt->GetAlignOf()) + return dt->GetAlignOf(); + Error("TStreamerLoop::GetAlignment", "Cannot determine alignment for type %d (bare type %d) for element %s", fType, + bareType, GetName()); + return alignof(std::max_align_t); +} + //////////////////////////////////////////////////////////////////////////////// /// return address of counter @@ -1290,6 +1352,21 @@ Int_t TStreamerObject::GetSize() const return classSize; } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the alignment of the object class in bytes. + +std::size_t TStreamerObject::GetAlignment() const +{ + TClass *cl = GetNewClass(); + if (!cl) + cl = GetClassPointer(); + if (cl && cl->GetClassAlignment()) + return cl->GetClassAlignment(); + // The caller will complains if the missing alignment information + // causes a problem. + return 0; +} + //////////////////////////////////////////////////////////////////////////////// /// Stream an object of class TStreamerObject. @@ -1386,6 +1463,21 @@ Int_t TStreamerObjectAny::GetSize() const return classSize; } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the alignment of the object (non-TObject) class in bytes. + +std::size_t TStreamerObjectAny::GetAlignment() const +{ + TClass *cl = GetNewClass(); + if (!cl) + cl = GetClassPointer(); + if (cl && cl->GetClassAlignment()) + return cl->GetClassAlignment(); + // The caller will complains if the missing alignment information + // causes a problem. + return 0; +} + //////////////////////////////////////////////////////////////////////////////// /// Stream an object of class TStreamerObjectAny. @@ -1923,6 +2015,21 @@ Int_t TStreamerSTL::GetSize() const return size; } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the alignment of the STL container in bytes. + +std::size_t TStreamerSTL::GetAlignment() const +{ + TClass *cl = GetNewClass(); + if (!cl) + cl = GetClassPointer(); + if (cl && cl->GetClassAlignment()) + return cl->GetClassAlignment(); + // The caller will complains if the missing alignment information + // causes a problem. + return 0; +} + //////////////////////////////////////////////////////////////////////////////// /// Print the content of the element. diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index 2184303c5fe51..d4ff40c5349e9 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -8260,6 +8260,14 @@ std::string TCling::CallFunc_GetWrapperCode(CallFunc_t *func) const // ClassInfo interface // +//////////////////////////////////////////////////////////////////////////////// + +size_t TCling::ClassInfo_AlignOf(ClassInfo_t *cinfo) const +{ + TClingClassInfo *TClinginfo = (TClingClassInfo *)cinfo; + return TClinginfo->GetAlignOf(); +} + //////////////////////////////////////////////////////////////////////////////// /// Return true if the entity pointed to by 'declid' is declared in /// the context described by 'info'. If info is null, look into the diff --git a/core/metacling/src/TCling.h b/core/metacling/src/TCling.h index 36b1bce8812e1..66e32f6502516 100644 --- a/core/metacling/src/TCling.h +++ b/core/metacling/src/TCling.h @@ -447,6 +447,7 @@ class TCling final : public TInterpreter { void* ClassInfo_New(ClassInfo_t* info, void* arena) const final; Long_t ClassInfo_Property(ClassInfo_t* info) const final; int ClassInfo_Size(ClassInfo_t* info) const final; + size_t ClassInfo_AlignOf(ClassInfo_t* info) const final; Longptr_t ClassInfo_Tagnum(ClassInfo_t* info) const final; const char* ClassInfo_FileName(ClassInfo_t* info) const final; const char* ClassInfo_FullName(ClassInfo_t* info) const final; diff --git a/core/metacling/src/TClingClassInfo.cxx b/core/metacling/src/TClingClassInfo.cxx index 005c17ffcaeaa..61403c9f5fe39 100644 --- a/core/metacling/src/TClingClassInfo.cxx +++ b/core/metacling/src/TClingClassInfo.cxx @@ -51,6 +51,8 @@ but the class metadata comes from the Clang C++ compiler, not CINT. #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" +#include "ROOT/RAlignmentUtils.hxx" + #include #include @@ -1317,6 +1319,12 @@ int TClingClassInfo::RootFlag() const return 0; } +/// Return the size of the class in bytes as reported by clang. +/// +/// Returns -1 if the class info is invalid, 0 for a forward-declared class, +/// an enum, or a class with no definition, and 1 for a namespace (a special +/// value inherited from CINT). For all other cases the actual byte size +/// obtained from the clang ASTRecordLayout is returned. int TClingClassInfo::Size() const { if (!IsValid()) { @@ -1355,6 +1363,46 @@ int TClingClassInfo::Size() const return clang_size; } +/// Return the alignment of the class in bytes as reported by clang. +/// +/// Returns (size_t)-1 if the class info is invalid, 0 for a forward-declared +/// class, an enum, a namespace or or a class with no definition. For all other +/// cases the actual alignment obtained from the clang ASTRecordLayout is +/// returned. +size_t TClingClassInfo::GetAlignOf() const +{ + if (!IsValid()) { + return -1; + } + if (!GetDecl()) { + // A forward declared class. + return 0; + } + + R__LOCKGUARD(gInterpreterMutex); + + Decl::Kind DK = GetDecl()->getKind(); + if (DK == Decl::Namespace) { + return 0; + } else if (DK == Decl::Enum) { + return 0; + } + const RecordDecl *RD = llvm::dyn_cast(GetDecl()); + if (!RD) { + return -1; + } + if (!RD->getDefinition()) { + // Forward-declared class. + return 0; + } + ASTContext &Context = GetDecl()->getASTContext(); + cling::Interpreter::PushTransactionRAII RAII(fInterp); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + auto align = Layout.getAlignment().getQuantity(); + assert(ROOT::Internal::IsValidAlignment(align)); + return align; +} + Longptr_t TClingClassInfo::Tagnum() const { if (!IsValid()) { diff --git a/core/metacling/src/TClingClassInfo.h b/core/metacling/src/TClingClassInfo.h index c08fa1bdae1c9..a4a9e96e0d0f3 100644 --- a/core/metacling/src/TClingClassInfo.h +++ b/core/metacling/src/TClingClassInfo.h @@ -181,6 +181,7 @@ class TClingClassInfo final : public TClingDeclInfo { long Property() const; int RootFlag() const; int Size() const; + size_t GetAlignOf() const; Longptr_t Tagnum() const; const char *FileName(); void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const; diff --git a/core/zip/src/RZip.cxx b/core/zip/src/RZip.cxx index ec5e0ae95e518..38b020a3459c7 100644 --- a/core/zip/src/RZip.cxx +++ b/core/zip/src/RZip.cxx @@ -48,13 +48,7 @@ static void R__unzipZLIB(int *srcsize, const unsigned char *src, int *tgtsize, u is done. LZ4 typically has the worst compression ratios, but much faster decompression speeds - sometimes by an order of magnitude. */ -#ifdef R__HAS_DEFAULT_ZSTD -ROOT::RCompressionSetting::EAlgorithm::EValues R__ZipMode = ROOT::RCompressionSetting::EAlgorithm::EValues::kZSTD; -#elif defined(R__HAS_DEFAULT_LZ4) -ROOT::RCompressionSetting::EAlgorithm::EValues R__ZipMode = ROOT::RCompressionSetting::EAlgorithm::EValues::kLZ4; -#else ROOT::RCompressionSetting::EAlgorithm::EValues R__ZipMode = ROOT::RCompressionSetting::EAlgorithm::EValues::kZLIB; -#endif /* =========================================================================== Function to set the ZipMode diff --git a/doc/index.html b/doc/index.html deleted file mode 100644 index a6629446b2b89..0000000000000 --- a/doc/index.html +++ /dev/null @@ -1,6 +0,0 @@ -

These pages contain the documentation for all ROOT classes, and the conceptual structure of the ROOT classes, its modules. -The documentation can be accessed by browsing the modules below, -by accessing a certain class directly using the Class Index, -or by simply searching the reference guide (see search field above). -The ROOT Tutorials show how to use many of ROOT's classes. -

diff --git a/doc/v520/Trailer.html b/doc/v520/Trailer.html deleted file mode 100644 index 40b15aab3909c..0000000000000 --- a/doc/v520/Trailer.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid HTML 4.01 Transitional -
-
-
- - - diff --git a/doc/v520/index.html b/doc/v520/index.html deleted file mode 100644 index 14095437fae8b..0000000000000 --- a/doc/v520/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - ROOT Version 5.20/00 Release Notes - - - - - - - - -

ROOT Version 5.20/00 Release Notes

-
-

ROOT version 5.20/00 has been released June 25, 2008. -In case you are upgrading from version 5.14, please read the releases notes -of version 5.16 and version 5.18 in addition to these notes.

-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
-

Binaries for all supported platforms are available at: -

-
      http://root.cern.ch/root/Version520.html
-Versions for AFS have also been updated. See the list of supported -platforms: -
      http://root.cern.ch/Welcome.html
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:
-Ilka Antcheva,
-Jean-Franois Bastien,
-Bertrand Bellenot,
-Rene Brun,
-Philippe Canal,
-Olivier Couet,
-Valeri Fine,
-Leo Franco,
-Gerri Ganis,
-Andrei Gheata,
-Mihaela Gheata,
-David Gonzalez Maline,
-Andreas Hoecker,
-Jan Iwaszkiewicz,
-Lukasz Janyst,
-Anna Kreshuk,
-Wim Lavrijsen,
-Sergei Linev,
-Anar Manafov,
-Diego Marcos-Segura,
-Lorenzo Moneta,
-Axel Naumann,
-Mathieu de Naurois,
-Eddy Offermann,
-Valeriy Onuchin,
-Timur Pocheptsov,
-Fons Rademakers,
-Paul Russo,
-Alja Tadel,
-Matevz Tadel,
-Wouter Verkerke,
-Guido Volpi,
-Hady Zalek
-

diff --git a/doc/v522/Trailer.html b/doc/v522/Trailer.html deleted file mode 100644 index 40b15aab3909c..0000000000000 --- a/doc/v522/Trailer.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid HTML 4.01 Transitional -
-
-
- - - diff --git a/doc/v522/index.html b/doc/v522/index.html deleted file mode 100644 index f9ad780b7c988..0000000000000 --- a/doc/v522/index.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - ROOT Version 5.22/00 Release Notes - - - - - - - - -

ROOT Version 5.22/00 Release Notes

-
-

ROOT version 5.22/00 has been released on December 18, 2008. -In case you are upgrading from an old version, please read the releases notes -of version 5.16, 5.18 and version 5.20 in addition to these notes.

-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
-

Binaries for all supported platforms are available at: -

-
      http://root.cern.ch/root/Version521.html
-Versions for AFS have also been updated. See the list of supported -platforms: -
      http://root.cern.ch/Welcome.html
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:
-Ilka Antcheva,
-Jean-Franois Bastien,
-Bertrand Bellenot,
-Rene Brun,
-Philippe Canal,
-Olivier Couet,
-Kyle Cranmer,
-Valeri Fine,
-Leo Franco,
-Gerri Ganis,
-Andrei Gheata,
-Mihaela Gheata,
-David Gonzalez Maline,
-Andreas Hoecker,
-Jan Iwaszkiewicz,
-Lukasz Janyst,
-Anna Kreshuk,
-Wim Lavrijsen,
-Josef Leydold,
-Sergei Linev,
-Anar Manafov,
-Diego Marcos-Segura,
-Lorenzo Moneta,
-Axel Naumann,
-Eddy Offermann,
-Timur Pocheptsov,
-Fons Rademakers,
-Paul Russo,
-Gregory Schott,
-Stefan Schmitt,
-Alja Tadel,
-Matevz Tadel,
-Wouter Verkerke,
-Hady Zalek
-Igor Smirnov
-

diff --git a/doc/v524/Trailer.html b/doc/v524/Trailer.html deleted file mode 100644 index 40b15aab3909c..0000000000000 --- a/doc/v524/Trailer.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid HTML 4.01 Transitional -
-
-
- - - diff --git a/doc/v524/index.html b/doc/v524/index.html deleted file mode 100644 index d8d0aa7568724..0000000000000 --- a/doc/v524/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - ROOT Version 5.24/00 Release Notes - - - - - - - - -

ROOT Version 5.24/00 Release Notes

-
-

ROOT version 5.24/00 will be released end of June 2009. -In case you are upgrading from an old version, please read the releases notes -of version 5.16, 5.18, 5.20 and version 5.22 in addition to these notes.

-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
-

Binaries for all supported platforms are available at: -

-
      http://root.cern.ch/root/Version521.html
-Versions for AFS have also been updated. See the list of supported -platforms: -
      http://root.cern.ch/Welcome.html
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:
-Kevin Belasco, N/A, Princeton University for MCMC,
-Bertrand Bellenot, CERN/SFT,
-Rene Brun, CERN/SFT,
-Philippe Canal, FNAL,
-Or Cohen, CERN & Weizmann, TMVA
-Olivier Couet, CERN/SFT,
-Kyle Cranmer, NYU/Atlas, RooStats
-Dominik Dannheim, MPI-Munich/Atlas, TMVA
-Valeri Fine, BNL/STAR,
-Gerri Ganis, CERN/SFT,
-Andrei Gheata, CERN/Alice,
-Mihaela Gheata, CERN/Alice,
-David Gonzalez Maline, CERN/SFT,
-Roberto Gracia Del Bao, Universidad de Valencia, recorder,
-Andreas Hoecker, CERN/Atlas, TMVA
-Jan Iwaszkiewicz, CERN,
-Lukasz Janyst, CERN/IT,
-Anna Kreshuk, GSI,
-Wim Lavrijsen, LBNL, PyRoot
-Alfio Lazzaro, Milano/AtlasMinuit
-George Lewis, New York University/Atlas for SPlot,
-Josef Leydold, TU Vienna, Unuran
-Sergei Linev, GSI,
-Johan Lundberg, CERN/Atlas, class TRolke
-Anar Manafov, GSI,
-Lorenzo Moneta, CERN/SFT,
-Axel Naumann, CERN/SFT,
-Eddy Offermann, Renaissance,
-Katerina Opocenska, Charles University of Prague, recorder,
-Rustem Ospanov, CERN/Atlas, TMVA
-Mario Pelliccioni, Turin/CMS, RooStats
-Timur Pocheptsov, JINR/Dubna,
-Fons Rademakers, CERN/SFT,
-Paul Russo, FNAL,
-Manuel Schiller, Heidelberg/LHCb, SMatrix,
-Gregory Schott, Karlsruhe/CMS, RooStats
-Stefan Schmitt, DESY, TUnfold
-Peter Speckmayer, CERN/Atlas, TMVA
-Joerg Stelzer, DESY/Atlas, TMVA
-Matthew Strait, umn.edu, doc
-Alja Tadel, CERN/CMS, Eve
-Matevz Tadel, CERN/Alice, Eve
-Jan Therhaag, Bonn/Atlas, TMVA
-Eckhard von Toerne, Bonn/Atlas, TMVA
-Wouter Verkerke, NIKHEF/Atlas, RooFit
-Alexander Voigt, Dresden/Atlas, TMVA
-Helge Voss, MPI-K-Heidelberg/Atlas, TMVA
-Andrzej Zemlja, IFJ-Krakow/Atlas
-

diff --git a/doc/v526/Trailer.html b/doc/v526/Trailer.html deleted file mode 100644 index 973a8b8be8065..0000000000000 --- a/doc/v526/Trailer.html +++ /dev/null @@ -1,17 +0,0 @@ - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid XHTML 1.0 Transitional -
-
-
- - - diff --git a/doc/v526/index.html b/doc/v526/index.html deleted file mode 100644 index c81fc1484c705..0000000000000 --- a/doc/v526/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - -ROOT Version 5.26/00 Release Notes - - - - - - - - -
- - -
-ROOT - - » Download - » Release Notes -
-
-

ROOT Version 5.26/00 Release Notes

- -
-

ROOT version 5.26/00 will be released on December 15 2009. -In case you are upgrading from an old version, please read the releases notes -of version 5.16, 5.18, 5.20, 5.22 and version 5.24 in addition to these notes.

-
-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • RooStats - a collection of statistical tools
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
-

Binaries for all supported platforms are available at: -

-
      https://root.cern/releases/release-52600/
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:
-Bertrand Bellenot, CERN/SFT,
-Brian Bockelman, UNL,
-Rene Brun, CERN/SFT,
-Philippe Canal, FNAL,
-Olivier Couet, CERN/SFT,
-Kyle Cranmer, NYU/Atlas, RooStats
-Valeri Fine, BNL/STAR,
-Lucie Flekova, CERN/SFT summer student,
-Fabrizio Furano, CERN/IT,
-Gerri Ganis, CERN/SFT,
-Andrei Gheata, CERN/Alice,
-Mary-Louise Gill, CERN/SFT summer student,
-David Gonzalez Maline, CERN/SFT,
-Andreas Hoecker, CERN/Atlas, TMVA
-Louis Höfler,
-Jan Iwaszkiewicz, CERN,
-Daniele Kruse, CERN, GDML
-Wim Lavrijsen, LBNL, PyRoot
-Alfio Lazzaro, Milano/AtlasMinuit
-Sergei Linev, GSI,
-Anar Manafov, GSI,
-Lorenzo Moneta, CERN/SFT,
-Axel Naumann, CERN/SFT,
-Eddy Offermann, Renaissance,
-Danilo Piparo, Karlsruhe/CMS, RooStats,
-Timur Pocheptsov, JINR/Dubna,
-Fons Rademakers, CERN/SFT,
-Philip Rodrigues, Oxford, Doc,
-Paul Russo, FNAL,
-Gregory Schott, Karlsruhe/CMS, RooStats,
-Tomasz Sosnicki, CERN/SFT summer student,
-Joerg Stelzer, DESY/Atlas, TMVA
-Matthew Strait, UMN.edu DOC
-Alja Tadel, CERN/CMS, Eve
-Matevz Tadel, CERN/Alice, Eve
-Wouter Verkerke, NIKHEF/Atlas, RooFit,
-Matthias Wolf, Karlsruhe/CMS, RooStats
-

diff --git a/doc/v528/Trailer.html b/doc/v528/Trailer.html deleted file mode 100644 index 973a8b8be8065..0000000000000 --- a/doc/v528/Trailer.html +++ /dev/null @@ -1,17 +0,0 @@ - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid XHTML 1.0 Transitional -
-
-
-
- - diff --git a/doc/v528/index.html b/doc/v528/index.html deleted file mode 100644 index 2fcc60ef290d2..0000000000000 --- a/doc/v528/index.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - -ROOT Version 5.28/00 Release Notes - - - - - - - - -
- - -
-ROOT - - » Download - » Release Notes -
-
-

ROOT Version 5.28/00 Release Notes

- -
-

ROOT version 5.28/00 has been released on December 15 2010. -In case you are upgrading from an old version, please read the releases notes -of version 5.16, 5.18, 5.20, 5.22, 5.24 and version 5.26 in addition to these notes.

-
-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • RooStats - a collection of statistical tools
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
  • Tutorials - ROOT's Tutorials
  • -
-

Binaries for all supported platforms are available at: -

-
      https://root.cern/releases/release-52800/
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:
-Alberto Annovi, INFN, TH1,
-Kevin Belasco, Princeton University, RooStats,
-Bertrand Bellenot, CERN/SFT,
-Rene Brun, CERN/SFT,
-Philippe Canal, FNAL,
-Olivier Couet, CERN/SFT,
-Kyle Cranmer, NYU, RooStats,
-Jason Detwiler, LBL, TClonesArray,
-Valeri Fine, BNL/STAR,
-Fabrizio Furano, CERN/IT,
-Gerri Ganis, CERN/SFT,
-Andrei Gheata, CERN/Alice,
-Oleksandr Grebenyuk, GSI, TLatex, TPostScript,
-Christian Gumpert, CERN and University Dresden, TEfficiency
-Bill Heintzelman, UPENN, TTree,
-Andreas Hoecker, CERN/Atlas, TMVA,
-Pierre Juillot, IN2P3, PostScript,
-Folkert Koetsveld, Nijmegen, RooFit,
-Alex Koutsman, Nikhef, RooFit,
-Sven Kreiss, NYU, RooStats,
-Wim Lavrijsen, LBNL, PyRoot,
-Sergei Linev, GSI,
-Benno List, Desy, MathCore and MathMore,
-Anar Manafov, GSI,
-Mike Marino, TUM, pyroot/tutorials
-Ramon Medrano Llamas, University of Oviedo, PROOF
-Biagio di Micco, Pythia8,
-Lorenzo Moneta, CERN/SFT,
-Axel Naumann, CERN/SFT,
-Eddy Offermann, Renaissance,
-Bartolomeu Rabacal, CERN/ADL, Math,
-Fons Rademakers, CERN/SFT,
-Paul Russo, FNAL,
-Sangsu Ryu, KISTI, PROOF
-Stefan Schmitt, Desy, TUnfold,
-Gregory Schott, Karlsruhe/CMS, RooStats,
-Benoit Speckel, IN2P3, Fonts,
-Peter Speckmayer, CERN, CLIC, TMVA,
-Joerg Stelzer, DESY/Atlas, TMVA,
-Alja Tadel, CERN/CMS, Eve,
-Matevz Tadel, CERN/Alice, Eve,
-Jan Therhaag, University Bonn, ATLAS, TMVA,
-Eckhard von Toerne, University Bonn, ATLAS, TMVA,
-Wouter Verkerke, NIKHEF/Atlas, RooFit,
-Helge Voss, MPI Heidelberg, LHCb, TMVA
-

diff --git a/doc/v530/Trailer.html b/doc/v530/Trailer.html deleted file mode 100644 index 973a8b8be8065..0000000000000 --- a/doc/v530/Trailer.html +++ /dev/null @@ -1,17 +0,0 @@ - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid XHTML 1.0 Transitional -
-
-
-
- - diff --git a/doc/v530/index.html b/doc/v530/index.html deleted file mode 100644 index 1814279f0f7fb..0000000000000 --- a/doc/v530/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - -ROOT Version 5.30/00 Release Notes - - - - - - - - -
- - -
-ROOT - - » Download - » Release Notes -
-
-

ROOT Version 5.30/00 Release Notes

- -
-

ROOT version 5.28/00 has been released on December 15 2010. -In case you are upgrading from an old version, please read the releases notes -of version 5.16, 5.18, 5.20, 5.22, 5.24, 5,26 and version 5.28 in addition to these notes.

-

-The release of version 5.30 is scheduled for June 27, 2011. -

-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • RooStats - a collection of statistical tools
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
  • Tutorials - ROOT's Tutorials
  • -
-

Binaries for all supported platforms are available at: -

-
      https://root.cern/releases/release-52800/
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:
-Bertrand Bellenot, CERN/SFT,
-Dario Berzano, INFN and University of Torino, ALICE, Proof,
-Rene Brun, CERN/SFT,
-Philippe Canal, FNAL,
-Olivier Couet, CERN/SFT,
-Kyle Cranmer, NYU, RooStats,
-Gerri Ganis, CERN/SFT,
-Andrei Gheata, CERN/Alice,
-Wim Lavrijsen, LBNL, PyRoot,
-Sergei Linev, GSI,
-Lorenzo Moneta, CERN/SFT,
-Axel Naumann, CERN/SFT,
-Eddy Offermann, Renaissance,
-Bartolomeu Rabacal, CERN/ADL, Math,
-Fons Rademakers, CERN/SFT,
-Paul Russo, FNAL,
-Joerg Stelzer, DESY/Atlas, TMVA,
-Alja Tadel, UCSD/CMS, Eve,
-Matevz Tadel, UCSD/CMS, Eve,
-Eckhard von Toerne, University Bonn, ATLAS, TMVA,
-Wouter Verkerke, NIKHEF/Atlas, RooFit,
-

diff --git a/doc/v532/Trailer.html b/doc/v532/Trailer.html deleted file mode 100644 index 973a8b8be8065..0000000000000 --- a/doc/v532/Trailer.html +++ /dev/null @@ -1,17 +0,0 @@ - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid XHTML 1.0 Transitional -
-
-
-
- - diff --git a/doc/v532/index.html b/doc/v532/index.html deleted file mode 100644 index 002ce23d379ac..0000000000000 --- a/doc/v532/index.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - -ROOT Version 5.32/00 Release Notes - - - - - - - - -
- - -
-ROOT - - » Download - » Release Notes -
-
-

ROOT Version 5.32/00 Release Notes

- -
-

ROOT version 5.32/00 has been released on Nov 29, 2011. -In case you are upgrading from an old version, please read the releases notes -of version 5.26, 5,28 and version 5.30 in addition to these notes.

-

-The release of version 5.34 is scheduled for May 29, 2012. -

-
-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • RooStats - a collection of statistical tools
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
  • Tutorials - ROOT's Tutorials
  • -
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:

-Bertrand Bellenot, CERN/SFT,
-Rene Brun, CERN/SFT,
-Philippe Canal, FNAL,
-Olivier Couet, CERN/SFT,
-Kyle Cranmer, NYU/ATLAS, RooStats,
-Sven Kreiss, NYU/ATLAS, RooStats,
-Gena Kukartsev, CERN and FNAL/CMS,
-Gerri Ganis, CERN/SFT,
-Andrei Gheata, CERN/Alice,
-Christian Gumpert, CERN and University Dresden/ATLAS, Math,
-Wim Lavrijsen, LBNL, PyRoot,
-Sergei Linev, GSI,
-Lorenzo Moneta, CERN/SFT,
-Axel Naumann, CERN/SFT,
-Eddy Offermann, Renaissance,
-Giovanni Petrucciani, UCSD/CMS, RooStats,
-Fons Rademakers, CERN/SFT,
-Paul Russo, FNAL,
-Joerg Stelzer, DESY/Atlas, TMVA,
-Alja Tadel, UCSD/CMS, Eve,
-Matevz Tadel, UCSD/CMS, Eve,
-Eckhard von Toerne, University Bonn, ATLAS, TMVA,
-Wouter Verkerke, NIKHEF/Atlas, RooFit,
diff --git a/doc/v534/Trailer.html b/doc/v534/Trailer.html deleted file mode 100644 index 973a8b8be8065..0000000000000 --- a/doc/v534/Trailer.html +++ /dev/null @@ -1,17 +0,0 @@ - -
-
-
-
ROOT page - - Class index - - Top of the page - - - Valid XHTML 1.0 Transitional -
-
-
-
- - diff --git a/doc/v534/index.html b/doc/v534/index.html deleted file mode 100644 index 1f639bce91ec7..0000000000000 --- a/doc/v534/index.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - -ROOT Version 5.33/01 Release Notes - - - - - - - - -
- - -
-ROOT - - » Download - » Release Notes -
-
-

ROOT Version 5.33/01 Release Notes

- -
-

ROOT version 5.32/00 has been released on November 29, 2011. -In case you are upgrading from an old version, please read the releases notes -of version 5.26, 5,28 and version 5.30 in addition to these notes.

-

-The release of version 5.34 is scheduled for May 30, 2012. -

-
-
    -
  • Bindings - packages related to the interplay with other programming languages (Python, Ruby)
  • -
  • Cint - the C++ interpreter
  • -
  • Core - the basic ROOT functionality
  • -
  • Geometry - building, representing and drawing geometrical objects
  • -
  • 2D Graphics - ROOT's two dimensional graphics interface
  • -
  • 3D Graphics - ROOT's three dimensional graphics interface
  • -
  • Graphical User Interface - from basic GUI elements to ROOT's own, complete dialogs
  • -
  • Histograming - counting values, spectra, and drawing them
  • -
  • HTML - the documentation generator
  • -
  • Input/Ouput - storing and reading data
  • -
  • Mathemathics - everything one can use to calculate: minimizers, matrixes, FFT, and much more
  • -
  • Miscellaneous - things that didn't make it into the other groups: table
  • -
  • Monte Carlo - monte carlo and physics simulation interfaces
  • -
  • Networking - network-related parts, e.g. protocols and authentication interfaces
  • -
  • PROOF - parallel ROOT facility
  • -
  • RooFit - a fitting library
  • -
  • RooStats - a collection of statistical tools
  • -
  • SQL - database interfaces
  • -
  • TMVA - multivariate analysis tools
  • -
  • Trees - ROOT's unique container class and related utilities
  • -
  • Tutorials - ROOT's Tutorials
  • -
-

-For more information, see: -

-
      http://root.cern.ch
-

The following people have contributed to this new version:

-Bertrand Bellenot, CERN/SFT,
-Rene Brun, CERN/SFT,
-Philippe Canal, FNAL,
-Olivier Couet, CERN/SFT,
-Kyle Cranmer, NYU, RooStats,
-Gerri Ganis, CERN/SFT,
-Andrei Gheata, CERN/Alice,
-Wim Lavrijsen, LBNL, PyRoot,
-Lorenzo Moneta, CERN/SFT,
-Axel Naumann, CERN/SFT,
-Fons Rademakers, CERN/SFT,
-Paul Russo, FNAL,
-Joerg Stelzer, DESY/Atlas, TMVA,
-Alja Tadel, UCSD/CMS, Eve,
-Matevz Tadel, UCSD/CMS, Eve,
-Eckhard von Toerne, University Bonn, ATLAS, TMVA,
-Wouter Verkerke, NIKHEF/Atlas, RooFit,
diff --git a/doc/v600/Trailer.md b/doc/v600/Trailer.md deleted file mode 100644 index 424a02fdabe42..0000000000000 --- a/doc/v600/Trailer.md +++ /dev/null @@ -1,4 +0,0 @@ -
-[ROOT page](http://root.cern.ch) - [Class index](http://root.cern.ch/root/htmldoc/ClassIndex.html) - -[Top of the page](#TopOfPage) -
diff --git a/doc/v600/index.md b/doc/v600/index.md deleted file mode 100644 index d7adc3349a505..0000000000000 --- a/doc/v600/index.md +++ /dev/null @@ -1,45 +0,0 @@ -% ROOT Version 6.00/00 Release Notes -% May 2014 - - -## Introduction - -ROOT version 6.00/00 has been released on May 30, 2014. It introduces the new -Cling C++11 interpreter, replacing CINT that has served ROOT well for many years. - -For more information, see: - -[http://root.cern.ch](http://root.cern.ch) - -The following people have contributed to this new version: - - Bertrand Bellenot, CERN/SFT,\ - Dario Berzano, CERN/SFT,\ - Rene Brun, CERN/SFT,\ - Ioan Gabriel Bucur, CERN/SFT \ - Philippe Canal, FNAL,\ - Cristina Cristescu, CERN/SFT,\ - Olivier Couet, CERN/SFT,\ - Kyle Cranmer, NYU, RooStats,\ - Anders Eie, NTNU,\ - Gerri Ganis, CERN/SFT,\ - Andrei Gheata, CERN/Alice,\ - Wim Lavrijsen, LBNL, PyRoot,\ - Sergey Linev, GSI, http,\ - Anna-Pia Lohfink,\ - Pere Mato, CERN/SFT,\ - Lorenzo Moneta, CERN/SFT,\ - Axel Naumann, CERN/SFT,\ - Danilo Piparo, CERN/SFT,\ - Timur Pocheptsov, CERN/SFT,\ - Fons Rademakers, CERN/SFT,\ - Paul Russo, FNAL, \ - Joerg Stelzer, DESY/Atlas, TMVA, \ - Alja Tadel, UCSD/CMS, Eve, \ - Matevz Tadel, UCSD/CMS, Eve, \ - Eckhard von Toerne, University Bonn, ATLAS, TMVA, \ - Vassil Vassilev, CERN/SFT \ - Wouter Verkerke, NIKHEF/Atlas, RooFit, \ - Yue Shi Lai, MIT - - diff --git a/doc/v602/index.md b/doc/v602/index.md deleted file mode 100644 index 0682c19764f3f..0000000000000 --- a/doc/v602/index.md +++ /dev/null @@ -1,44 +0,0 @@ -% ROOT Version 6.02/00 Release Notes -% May 2014 - - -## Introduction - -ROOT version 6.02/00 has been released on [ ]. - -For more information, see: - -[http://root.cern.ch](http://root.cern.ch) - -The following people have contributed to this new version: - - Bertrand Bellenot, CERN/SFT,\ - Dario Berzano, CERN/SFT,\ - Rene Brun, CERN/SFT,\ - Ioan Gabriel Bucur, CERN/SFT \ - Philippe Canal, FNAL,\ - Cristina Cristescu, CERN/SFT,\ - Olivier Couet, CERN/SFT,\ - Kyle Cranmer, NYU, RooStats,\ - Anders Eie, NTNU,\ - Gerri Ganis, CERN/SFT,\ - Andrei Gheata, CERN/Alice,\ - Wim Lavrijsen, LBNL, PyRoot,\ - Sergey Linev, GSI, http,\ - Anna-Pia Lohfink,\ - Pere Mato, CERN/SFT,\ - Lorenzo Moneta, CERN/SFT,\ - Axel Naumann, CERN/SFT,\ - Danilo Piparo, CERN/SFT,\ - Timur Pocheptsov, CERN/SFT,\ - Fons Rademakers, CERN/SFT,\ - Paul Russo, FNAL, \ - Joerg Stelzer, DESY/Atlas, TMVA, \ - Alja Tadel, UCSD/CMS, Eve, \ - Matevz Tadel, UCSD/CMS, Eve, \ - Eckhard von Toerne, University Bonn, ATLAS, TMVA, \ - Vassil Vassilev, CERN/SFT \ - Wouter Verkerke, NIKHEF/Atlas, RooFit, \ - Yue Shi Lai, MIT - - diff --git a/doc/v604/index.md b/doc/v604/index.md deleted file mode 100644 index d2c1363fdfead..0000000000000 --- a/doc/v604/index.md +++ /dev/null @@ -1,44 +0,0 @@ -% ROOT Version 6.04/00 Release Notes -% 2 June 2015 - - -## Introduction - -ROOT version 6.04/00 was released on 2 June, 2015. - -For more information, see: - -[http://root.cern.ch](http://root.cern.ch) - -The following people have contributed to this new version: - - David Abdurachmanov, CERN, CMS,\ - Bertrand Bellenot, CERN/SFT,\ - Rene Brun, CERN/SFT,\ - Philippe Canal, FNAL,\ - Cristina Cristescu, CERN/SFT,\ - Olivier Couet, CERN/SFT,\ - Kyle Cranmer, NYU, RooStats,\ - Gerri Ganis, CERN/SFT,\ - Andrei Gheata, CERN/Alice,\ - Lukasz Janyst, CERN/IT,\ - Christopher Jones, Fermilab, CMS,\ - Wim Lavrijsen, LBNL, PyRoot,\ - Sergey Linev, GSI, http,\ - Pere Mato, CERN/SFT,\ - Lorenzo Moneta, CERN/SFT,\ - Axel Naumann, CERN/SFT,\ - Danilo Piparo, CERN/SFT,\ - Timur Pocheptsov, CERN/SFT,\ - Fons Rademakers, CERN/SFT,\ - Enric Tejedor Saavedra, CERN/SFT,\ - Liza Sakellari, CERN/SFT,\ - Manuel Tobias Schiller,\ - David Smith, CERN/IT,\ - Matevz Tadel, UCSD/CMS, Eve, \ - Vassil Vassilev, CERN/SFT \ - Wouter Verkerke, NIKHEF/Atlas, RooFit, \ - Yue Shi Lai, MIT,\ - Maciej Zimnoch - - diff --git a/documentation/doxygen/htmlheader.html b/documentation/doxygen/htmlheader.html index 3d7c3a15f41c0..7c995cb74e4f6 100644 --- a/documentation/doxygen/htmlheader.html +++ b/documentation/doxygen/htmlheader.html @@ -1,5 +1,5 @@ - + diff --git a/documentation/doxygen/makeinput.sh b/documentation/doxygen/makeinput.sh index 607672652e981..9cd7cf1697eee 100755 --- a/documentation/doxygen/makeinput.sh +++ b/documentation/doxygen/makeinput.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script creates the file Doxyfile_INPUT which defines the list of directories to be # analysed by doxygen. To only build a subset of the documentation it is enough to comment diff --git a/documentation/doxygen/modifyNamespacesWebpage.sh b/documentation/doxygen/modifyNamespacesWebpage.sh index ac6ecabcce5f3..606ee623ddf78 100755 --- a/documentation/doxygen/modifyNamespacesWebpage.sh +++ b/documentation/doxygen/modifyNamespacesWebpage.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # The Python tutorials appear in the Namespaces page. # This script removes the namespace given as input from all the files. diff --git a/documentation/primer/rootDocPreprocessor.py b/documentation/primer/rootDocPreprocessor.py index 1e1ae917c8268..6dbdbf522df3e 100755 --- a/documentation/primer/rootDocPreprocessor.py +++ b/documentation/primer/rootDocPreprocessor.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 """ A tool to preprocess root documentation in order to provide missing functionality in the documentation tools like doxygen or pandoc. @@ -14,8 +14,8 @@ usage="Usage: %s fileToBeTreated.md\n" %__file__ def printErrAndUsage(msg): - print msg - print usage + print(msg) + print(usage) def checkInvocation(argv): """ @@ -49,7 +49,7 @@ def includeFilter(text): if line.startswith("@ROOT_INCLUDE_FILE"): inclFileName = line.split()[1] if not os.path.exists(inclFileName): - print "[includeFilter] Error: file %s does not exist." %inclFileName + print("[includeFilter] Error: file", inclFileName, "does not exist.") retcode+=1 continue for inclFileLine in open(inclFileName).readlines(): @@ -91,7 +91,7 @@ def preprocessFile(): filename = argv[1] retcode = applyFilters(filename) if retcode != 0: - print "Errors during the preprocessing." + print("Errors during the preprocessing.") return retcode if __name__ == "__main__": diff --git a/documentation/tmva/UsersGuide/MyQuestions.txt b/documentation/tmva/UsersGuide/MyQuestions.txt deleted file mode 100644 index b372f05ac5d67..0000000000000 --- a/documentation/tmva/UsersGuide/MyQuestions.txt +++ /dev/null @@ -1,33 +0,0 @@ - -1) - - -der Path der im svn co example gegeben wir existiert nicht. es gibt KEIN - -hvoss@hvlhcb01:~/TMVA$ svn list https://root.cern.ch/svn/root/branches/dev/tmvapatches -v5-26-00-patches/ -hvoss@hvlhcb01:~/TMVA$ svn list https://root.cern.ch/svn/root/branches/dev/tmvapatches/v5-26-00-patches -tmva/ -hvoss@hvlhcb01:~/TMVA$ svn list https://root.cern.ch/svn/root/branches/dev/tmvapatches/v5-26-00-patches/tmva -Makefile -Makefile.arch -Module.mk -doc/ -inc/ -src/ -test/ - -das eine Versions nummer mit TMVA Version hat !! Es gibt nur ROOT Versionsnummern und -darunter ein tmva subdirectory. - - SCHADE eigentlich !! - -------------------- - sollen/koennen wir das aendern? Wenn ja, wie ? - - -2) Was mache ich mit der arXiv und CERN-Report Nummer im updated UsersGuide ? - -3) Kann irgendjemand der weis wie's implementiert ist, die "NumEvent" "EqualNumEvents" Geschichte und wie das gehandhabt wird (i.e. relative etc..) so formulieren dass man das versteht? - - - diff --git a/documentation/users-guide/.gitignore b/documentation/users-guide/.gitignore deleted file mode 100644 index 90ab79229e8c7..0000000000000 --- a/documentation/users-guide/.gitignore +++ /dev/null @@ -1,79 +0,0 @@ -ALittleC++.html -ALittleC++.pdf -AddingaClass.html -AddingaClass.pdf -CINT.html -CINT.pdf -CollectionClasses.html -CollectionClasses.pdf -ExampleAnalysis.html -ExampleAnalysis.pdf -FittingHistograms.html -FittingHistograms.pdf -FoldersTasks.html -FoldersTasks.pdf -Geometry.html -Geometry.pdf -GettingStarted.html -GettingStarted.pdf -Graphics.html -Graphics.pdf -Graphs.html -Graphs.pdf -HTMLDoc.html -HTMLDoc.pdf -Histograms.html -Histograms.pdf -InputOutput.html -InputOutput.pdf -InstallandBuild.html -InstallandBuild.pdf -Introduction.html -Introduction.pdf -LinearAlgebra.html -LinearAlgebra.pdf -MathLibraries.html -MathLibraries.pdf -Networking.html -Networking.pdf -ObjectOwnership.html -ObjectOwnership.pdf -PROOF.html -PROOF.pdf -PhysicsVectors.html -PhysicsVectors.pdf -Preface.html -Preface.pdf -PythonRuby.html -PythonRuby.pdf -ROOTUsersGuide.epub -ROOTUsersGuide.html -ROOTUsersGuide.pdf -ROOTUsersGuideA4.aux -ROOTUsersGuideA4.idx -ROOTUsersGuideA4.ilg -ROOTUsersGuideA4.ind -ROOTUsersGuideA4.log -ROOTUsersGuideA4.out -ROOTUsersGuideA4.pdf -ROOTUsersGuideA4.tex -ROOTUsersGuideA4.toc -ROOTUsersGuideLetter.aux -ROOTUsersGuideLetter.idx -ROOTUsersGuideLetter.ilg -ROOTUsersGuideLetter.ind -ROOTUsersGuideLetter.log -ROOTUsersGuideLetter.out -ROOTUsersGuideLetter.pdf -ROOTUsersGuideLetter.tex -ROOTUsersGuideLetter.toc -ROOTandQt.html -ROOTandQt.pdf -Threads.html -Threads.pdf -Trees.html -Trees.pdf -TutorialsandTests.html -TutorialsandTests.pdf -WritingGUI.html -WritingGUI.pdf diff --git a/documentation/users-guide/ALittleC++.md b/documentation/users-guide/ALittleC++.md deleted file mode 100644 index 2308f565121ec..0000000000000 --- a/documentation/users-guide/ALittleC++.md +++ /dev/null @@ -1,430 +0,0 @@ -# A Little C++ -\index{C++} - -This chapter introduces you to some useful insights into C++, to allow -you to use some of the most advanced features in ROOT. It is in no case a -full course in C++. - -## Classes, Methods and Constructors - - -C++ extends C with the notion of a class. If you're used to structures -in C, a class is a `struct` that is a group of related variables, -which is extended with functions and routines specific to this -structure (class). What is the interest? Consider a `struct` that is defined this way: - -``` {.cpp} - struct Line { - float x1; - float y1; - float x2; - float y2; - } -``` - -This structure represents a line to be drawn in a graphical window. -`(x1,y1)` are the coordinates of the first point, `(x2,y2)` the -coordinates of the second point. In the standard C, if you want to -draw effectively such a line, you first have to define a structure and -initialize the points (you can try this): - -``` {.cpp} - Line firstline; - firstline.x1 = 0.2; - firstline.y1 = 0.2; - firstline.x2 = 0.8; - firstline.y2 = 0.9; -``` - -This defines a line going from the point `(0.2,0.2)` to the point -`(0.8,0.9)`. To draw this line, you will have to write a function, say -`LineDraw(Line l)` and call it with your object as argument: - -``` {.cpp} - LineDraw(firstline); -``` - -In C++, we would not do that. We would instead define a class like this: - -``` {.cpp} - class TLine { - Double_t x1; - Double_t y1; - Double_t x2; - Double_t y2; - TLine(int x1, int y1, int x2, int y2); - void Draw(); - } -``` - -Here we added two functions, that we will call methods or member -functions, to the **`TLine`** class. The first method is used for -initializing the line objects we would build. It is called a -constructor. The second one is the `Draw` method itself. Therefore, to -build and draw a line, we have to do: - -``` {.cpp} - TLine l(0.2,0.2,0.8,0.9); - l.Draw(); -``` - -The first line builds the object `l` by calling its constructor. The -second line calls the **`TLine`**`::Draw()` method of this object. You -don't need to pass any parameters to this method since it applies to -the object `l`, which knows the coordinates of the line. These are -internal variables `x1`, `y1`, `x2`, `y2` that were initialized by the -constructor. - -## Inheritance and Data Encapsulation - - -We have defined a **`TLine`** class that contains everything necessary -to draw a line. If we want to draw an arrow, is it so different from -drawing a line? We just have to draw a triangle at one end. It would -be very inefficient to define the class **`TArrow`** from scratch. -Fortunately, inheritance allows a class to be defined from an existing -class. We would write something like: - -``` {.cpp} - class TArrow : public TLine { - int ArrowHeadSize; - void Draw(); - void SetArrowSize(int arrowsize); - } -``` - -The keyword "`public`" will be explained later. The class **`TArrow`** -now contains everything that the class **`TLine`** does, and a couple -of more things, the size of the arrowhead and a function that can -change it. The Draw method of **`TArrow`** will draw the head and call -the draw method of **`TLine`**. We just have to write the code for -drawing the head! - -### Method Overriding - - -Giving the same name to a method (remember: method = member function -of a class) in the child class (**`TArrow`**) as in the parent -(**`TLine`**) does not give any problem. This is called **overriding** -a method. Draw in **`TArrow`** overrides Draw in **`TLine`**. There is -no possible ambiguity since, when one calls the `Draw()` method; this -applies to an object whose type is known. Suppose we have an object -`l` of type **`TLine`** and an object `a` of type **`TArrow`**. When -you want to draw the line, you do: - -``` {.cpp} - l.Draw(); -``` - -`Draw()` from **`TLine`** is called. If you do: - -``` {.cpp} - a.Draw(); -``` - -`Draw()` from **`TArrow`** is called and the arrow `a` is drawn. - -### Data Encapsulation - - -We have seen previously the keyword "`public`". This keyword means -that every name declared public is seen by the outside world. This is -opposed to "`private`" that means only the class where the name was -declared private could see this name. For example, suppose we declare -in **`TArrow`** the variable `ArrowHeadSize` private. - -``` {.cpp} - private: - int ArrowHeadSize; -``` - -Then, only the methods (i.e. member functions) of **`TArrow`** will be -able to access this variable. Nobody else will see it. Even the -classes that we could derive from **`TArrow`** will not see it. On the -other hand, if we declare the method `Draw()` as public, everybody will -be able to see it and use it. You see that the character public or -private does not depend of the type of argument. It can be a data -member, a member function, or even a class. For example, in the case -of **`TArrow`**, the base class **`TLine`** is declared as public: - -``` {.cpp} - class TArrow : public TLine { ... -``` - -This means that all methods of **`TArrow`** will be able to access all -methods of **`TLine`**, but this will be also true for anybody in the -outside world. Of course, this is true if **`TLine`** accepts the -outside world to see its methods/data members. If something is -declared private in **`TLine`**, nobody will see it, not even -**`TArrow`** members, even if **`TLine`** is declared as a public -base class. - -What if **`TLine`** is declared "`private`" instead of "`public`" ? -Well, it will behave as any other name declared private in -**`TArrow`**: only the data members and methods of **`TArrow`** will -be able to access **`TLine`**, its methods and data members, nobody -else. This may seem a little bit confusing and readers should read a -good C++ book if they want more details. Especially since, besides -public and private, a member can be protected. Usually, one puts -private the methods that the class uses internally, like some -utilities classes, and that the programmer does not want to be seen -in the outside world. - -With "good" C++ practice (which we have tried to use in ROOT), all -data members of a class are private. This is called data encapsulation -and is one of the strongest advantages of Object Oriented Programming -(OOP). Private data members of a class are not visible, except to the -class itself. So, from the outside world, if one wants to access those -data members, one should use so called "getters" and "setters" -methods, which are special methods used only to get or set the data -members. The advantage is that if the programmers want to modify the -inner workings of their classes, they can do so without changing what -the user sees. The user does not even have to know that something has -changed (for the better, hopefully). For example, in our **`TArrow`** -class, we would have set the data member `ArrowHeadSize` private. The -setter method is `SetArrowSize()`, we do not need a getter method: - -``` {.cpp} - class TArrow : public TLine { - private: - int ArrowHeadSize; - public: - void Draw(); - void SetArrowSize(int arrowsize); - } -``` - -To define an arrow object you call the constructor. This will also -call the constructor of **`TLine`**, which is the parent class of -**`TArrow`**, automatically. Then we can call any of the line or arrow -public methods: - -``` {.cpp} -root[] TArrow *myarrow = new TArrow(1,5,89,124); -root[] myarrow->SetArrowSize(10); -root[] myarrow->Draw(); -``` - -## Creating Objects on the Stack and Heap - - -To explain how objects are created on the stack and on the heap we -will use the `Quad` class. You can find the definition in -`$ROOTSYS/tutorials/quadp/Quad.h` and `Quad.cxx`. The `Quad` class -has four methods. The constructor and destructor, `Evaluate` that -evaluates `ax**2 + bx +c`, and `Solve` which solves the quadratic -equation `ax**2 + bx +c = 0`. - -`Quad.h` : - -``` {.cpp} - class Quad { - public: - Quad(Float_t a, Float_t b, Float_t c); - ~Quad(); - Float_t Evaluate(Float_t x) const; - void Solve() const; - private: - Float_t fA; - Float_t fB; - Float_t fC; - }; -``` - -`Quad.cxx`: - -``` {.cpp} - #include - #include - #include "Quad.h" - - Quad::Quad(Float_t a, Float_t b, Float_t c) { - fA = a; - fB = b; - fC = c; - } - Quad::~Quad() { - Cout <<"deleting object with coeffts: "<< fA << "," << fB << "," - << fC << endl; - } - Float_t Quad::Evaluate(Float_t x) const { - return fA*x*x + fB*x + fC; - } - void Quad::Solve() const { - Float_t temp = fB*fB - 4.*fA*fC; - if ( temp > 0. ) { - temp = sqrt( temp ); - cout << "There are two roots: " << ( -fB - temp ) / (2.*fA) - << " and " << ( -fB + temp ) / (2.*fA) << endl; - } else { - if ( temp == 0. ) { - cout << "There are two equal roots: " << -fB / (2.*fA) - << endl; - } else { - cout << "There are no roots" << endl; - } - } - } -``` - -Let us first look how we create an object. When we create an object -by: - -``` {.cpp} -root[] Quad my_object(1.,2.,-3.); -``` - -We are creating an object on the stack. A FORTRAN programmer may be -familiar with the idea; it is not unlike a local variable in a -function or subroutine. Although there are still a few old timers who -do not know it, FORTRAN is under no obligation to save local variables -once the function or subroutine returns unless the SAVE statement is -used. If not then it is likely that FORTRAN will place them on the -stack and they will "pop off" when the RETURN statement is reached. To -give an object more permanence it has to be placed on the heap. - -``` {.cpp} -root[] .L Quad.cxx -root[] Quad *my_objptr = new Quad(1.,2.,-3.); -``` - -The second line declares a pointer to `Quad` called `my_objptr`. From -the syntax point of view, this is just like all the other declarations -we have seen so far, i.e. this is a stack variable. The value of the -pointer is set equal to - -``` {.cpp} -new Quad(1.,2.,-3.); -``` - -`new`, despite its looks, is an operator and creates an object or -variable of the type that comes next, `Quad` in this case, on the -heap. Just as with stack objects it has to be initialized by calling -its constructor. The syntax requires that the argument list follows the -type. This one statement has brought two items into existence, one on -the heap and one on the stack. The heap object will live until the -delete operator is applied to it. - -There is no FORTRAN parallel to a heap object; variables either come -or go as control passes in and out of a function or subroutine, or, -like a COMMON block variables, live for the lifetime of the program. -However, most people in HEP who use FORTRAN will have experience of a -memory manager and the act of creating a bank is a good equivalent of -a heap object. For those who know systems like ZEBRA, it will come as -a relief to learn that objects do not move, C++ does not garbage -collect, so there is never a danger that a pointer to an object -becomes invalid for that reason. However, having created an object, -it is the user's responsibility to ensure that it is deleted when no -longer needed, or to pass that responsibility onto to some other -object. Failing to do that will result in a memory leak, one of the -most common and most hard-to-find C++ bugs. - -To send a message to an object via a pointer to it, you need to use -the "`->`" operator e.g.: - -``` {.cpp} -root[] my_objptr->Solve(); -``` - -Although we chose to call our pointer `my_objptr`, to emphasize that -it is a pointer, heap objects are so common in an object-oriented -program that pointer names rarely reflect the fact - you have to be -careful that you know if you are dealing with an object or its -pointer! Fortunately, the compiler won't tolerate an attempt to do -something like: - -``` {.cpp} -root[] my_objptr.Solve(); -``` - -As we have seen, heap objects -have to be accessed via pointers, whereas stack objects can be -accessed directly. They can also be accessed via pointers: - -``` {.cpp} -root[] Quad stack_quad(1.,2.,-3.); -root[] Quad *stack_ptr = &stack_quad; -root[] stack_ptr->Solve(); -``` - -Here we have a `Quad` pointer that has been initialized with the -address of a stack object. Be very careful if you take the address of -stack objects. As we shall see soon, they are deleted automatically, -which could leave you with an illegal pointer. Using it will corrupt -and may as well crash the program! - -It is time to look at the destruction of objects. A destructor is a -special C++ function that releases resources for (or destroys) an -object of a class. It is the opposite of a constructor that creates the -object of a class when it is called. The compiler will provide a -destructor that does nothing if none is provided. We will add one to -our Quad class so that we can see when it is called. The class names -the destructor but with a prefix \~ which is the C++ one's complement -i.e. bit wise complement, and hence has destruction overtones! We -declare it in the .h file and define it in the `.cxx` file. It does -not do much except print out that it has been called (still a useful -debug technique despite today's powerful debuggers!). - -Now run root, load the Quad class and create a heap object: - -``` {.cpp} -root[] .L Quad.cxx -root[] Quad *my_objptr = new Quad(1.,2.,-3.); -``` - -To delete the object: - -``` {.cpp} -root[] delete my_objptr; -root[] my_objptr = 0; -``` - -You should see the print out from its destructor. Setting the pointer -to zero afterwards is not strictly necessary (and Cling does it -automatically), but the object is no more accessible, and any attempt -to use the pointer again will, as has already been stated, cause -grief. So much for heap objects, but how are stack objects deleted? In -C++, a stack object is deleted as soon as control leaves the innermost -compound statement that encloses it. Therefore, it is singularly -futile to do something like: - -``` {.cpp} -root[] { Quad my_object(1.,2.,-3.); } -``` - -Cling does not follow this rule; if you type in the above line, you -will not see the destructor message. As explained in the Script -lesson, you can load in compound statements, which would be a bit -pointless if everything disappeared as soon as it was loaded! Instead, -to reset the stack you have to type: - -``` {.cpp} -root[] gROOT->Reset(); -``` - -This sends the Reset message via the global pointer to the ROOT -object, which, amongst its many roles, acts as a resource manager. -Start ROOT again and type in the following: - -``` {.cpp} -root[] .L Quad.cxx -root[] Quad my_object(1.,2.,-3.); -root[] Quad *my_objptr = new Quad(4.,5.,-6.); -root[] gROOT->Reset(); -``` - -You will see that this deletes the first object but not the second. We -have also painted ourselves into a corner, as `my_objptr` was also on -the stack. This command will fail. - -``` {.cpp} -root[] my_objptr->Solve(); -``` - -Cling no longer knows what `my_objptr` is. This is a great example of a -memory leak; the heap object exists but we have lost our way to access -it. In general, this is not a problem. If any object will outlive the -compound statement in which it was created then a more permanent -pointer will point to it, which frequently is part of another heap -object. See Resetting the Interpreter Environment in the chapter -"Cling the C++ Interpreter". diff --git a/documentation/users-guide/AddingaClass.md b/documentation/users-guide/AddingaClass.md deleted file mode 100644 index 0a4d287d3d6e9..0000000000000 --- a/documentation/users-guide/AddingaClass.md +++ /dev/null @@ -1,1212 +0,0 @@ -# Adding a Class - - -## The Role of TObject - - -The light-weight **`TObject`** class provides the default behavior and -protocol for the objects in the ROOT system. Specifically, it is the -primary interface to classes providing object I/O, error handling, -inspection, introspection, and drawing. The interface to this service is -via abstract classes. - -### Introspection, Reflection and Run Time Type Identification - - -Introspection, which is also referred to as reflection, or run time type -identification (RTTI) is the ability of a class to reflect upon itself -or to "look inside itself. ROOT implements reflection with the -**`TClass`** class. It provides all the information about a class, a -full description of data members and methods, including the comment -field and the method parameter types. A class with the `ClassDef` macro -has the ability to obtain a **`TClass`** with the `IsA` method. - -``` {.cpp} -TClass *cl = obj->IsA(); -``` - -It returns a **`TClass`**. In addition, an object can directly get the -class name and the base classes by: - -``` {.cpp} -const char* name = obj->ClassName(); -``` - -If the class is a descendent of **`TObject`**, you can check if an -object inherits from a specific class, you can use the `InheritsFrom` -method. This method returns `kTrue` if the object inherits from the -specified class name or **`TClass`**. - -``` {.cpp} -Bool_t b = obj->InheritsFrom("TLine"); -Bool_t b = obj->InheritsFrom(TLine::Class()); -``` - -ROOT and `Cling` rely on reflection and the class dictionary to identify -the type of a variable at run time. With **`TObject`** inheritance come -some methods that use Introspection to help you see the data in the -object or class. For instance: - -``` {.cpp} -obj->Dump(); // lists all data members and their current values -obj->Inspect(); // opens a window to browse data members -obj->DrawClass(); // Draws the class inheritance tree -``` - -For an example of `obj->Inspect()`, see "Inspecting Objects". - -### Collections - - -To store an object in a ROOT collection, it must be a descendent of -**`TObject`**. This is convenient if you want to store objects of -different classes in the same collection and execute the method of the -same name on all members of the collection. For example, the list of -graphics primitives are in a ROOT collection called **`TList`**. When -the canvas is drawn, the `Paint` method is executed on the entire -collection. Each member may be a different class, and if the `Paint` -method is not implemented, **`TObject::Paint`** will be executed. - -### Input/Output - - -The `TObject::Write` method is the interface to the ROOT I/O system. It -streams the object into a buffer using the `Streamer` method. It -supports cycle numbers and automatic schema evolution. See -"Input/Output". - -### Paint/Draw - - -These graphics methods are defaults; their implementation in -**`TObject`** does not use the graphics subsystem. The `TObject::Draw` -method is simply a call to `AppendPad`. The `Paint` method is empty. The -default is provided so that one can call `Paint` in a collection. The -method `GetDrawOption` returns the draw option that was used when the -object was drawn on the canvas. This is especially relevant with -histograms and graphs. - -### Clone/DrawClone - - -Two useful methods are `Clone` and `DrawClone`. The `Clone` method takes -a snapshot of the object with the `Streamer` and creates a new object. -The `DrawClone` method does the same thing and in addition draws the -clone. - -### Browse - - -This method is called if the object is browse-able and is to be -displayed in the object browser. For example the **`TTree`** -implementation of `Browse`, calls the Browse method for each branch. The -`TBranch::Browse` method displays the name of each leaf. For the -object's `Browse` method to be called, the `IsFolder()` method must be -overridden to return true. This does not mean it has to be a folder, it -just means that it is browse-able. - -### SavePrimitive - - -This method is called by a canvas on its list of primitives, when the -canvas is saved as a script. The purpose of `SavePrimitve` is to save a -primitive as a C++ statement(s). Most ROOT classes implement the -`SavePrimitive` method. It is recommended that the `SavePrimitive` is -implemented in user defined classes if it is to be drawn on a canvas. -Such that the command `TCanvas::SaveAs(Canvas.C)` will preserve the -user-class object in the resulting script. - -### GetObjectInfo - - -This method is called when displaying the event status in a canvas. To -show the event status window, select the `Options` menu and the -`EventStatus` item. This method returns a string of information about -the object at position (x, y). Every time the cursor moves, the object -under the cursor executes the `GetObjectInfo` method. The string is then -shown in the status bar. There is a default implementation in -**`TObject`**, but it is typically overridden for classes that can -report peculiarities for different cursor positions (for example the bin -contents in a TH1). - -### IsFolder - - -By default an object inheriting from **`TObject`** is not brows-able, -because **`TObject::IsFolder()`** returns `kFALSE`. To make a class -browse-able, the `IsFolder` method needs to be overridden to return -`kTRUE`. In general, this method returns `kTRUE` if the object contains -browse-able objects (like containers or lists of other objects). - -### Bit Masks and Unique ID - - -A **`TObject`** descendent inherits two data members: `fBits` and -`fUniqueID`. `fBits `is 32-bit data member used with a bit mask to get -object information. Bits 0 - 13 are reserved as global bits, bits 14 - -23 can be used in different class hierarchies. - -``` {.cpp} -enum EObjBits { - kCanDelete = BIT(0), // if can be deleted - kMustCleanup = BIT(3), // if destructor must call RecursiveRemove() - kObjInCanvas = BIT(3), // for backward compatibility only - kIsReferenced = BIT(4), // if referenced by TRef or TRefArray - kHasUUID = BIT(5), // if has a TUUID, fUniqueID=UUIDNumber - kCannotPick = BIT(6), // if cannot be picked in a pad - kNoContextMenu = BIT(8), // if does not want a context menu - kInvalidObject = BIT(13) // object ctor succeeded but the object should not be used -}; -``` - -For example, the bits `kMustCleanup` and `kCanDelete` are used in -**`TObject`**. See "The kCanDelete Bit" and "The kMustCleanup Bit". They -can be set by any object and should not be reused. Make sure not -to overlap them in any given hierarchy. The bit 13 (`kInvalidObject`) is -set when an object could not be read from a ROOT file. It will check -this bit and will skip to the next object on the file. - -The **`TObject`** constructor initializes the `fBits` to zero depending -if the object is created on the stack or allocated on the heap. When the -object is created on the stack, the `kCanDelete` bit is set to false to -protect from deleting objects on the stack. The high 8 bits are reserved -for the system usage; the low 24 bits are user settable. `fUniqueID` is -a data member used to give a unique identification number to an object. -It is initialized to zero by the **`TObject`** constructor. ROOT does -not use this data member. The two data members (`fBits` and `fUniqueID`) -are streamed out when writing an object to disk. If you do not use them, -you can save some space and time by specifying: - -``` {.cpp} -MyClass::Class()->IgnoreTObjectStreamer(); -``` - -This sets a bit in the **`TClass`** object. If the file is compressed, -the savings are minimal since most values are zero; however, it saves -some space when the file is not compressed. A call -to` IgnoreTObjectStreamer` also prevents the creation of two additional -branches when splitting the object. If left alone, two branches called -`fBits` and `fUniqueID` will appear. - -## Motivation - - -If you want to integrate and use your classes with ROOT, to enjoy -features like, extensive RTTI (Run Time Type Information) and ROOT -object I/O and inspection, you have to add the following line to your -class header files: - -``` {.cpp} -ClassDef(ClassName,ClassVersionID); //The class title -``` - -For example in `TLine.h` we have: - -``` {.cpp} -ClassDef(TLine,1); //A line segment -``` - -The **`ClassVersionID`** is used by the ROOT I/O system. It is written -on the output stream and during reading you can check this version ID -and take appropriate action depending on the value of the ID. See -"Streamers". Every time you change the data members of a class, you -should increase its `ClassVersionID` by one. The `ClassVersionID` should -be `>=1`. Set `ClassVersionID=0` in case you don't need object I/O. To -be able to generate properly documentation for your classes using -**`THtml`** you must add the statement: - -``` {.cpp} -ClassImp(ClassName) -``` - -For example in `TLine.cxx`: - -``` {.cpp} -ClassImp(TLine) -``` - -Note that you should provide a default constructor for your classes, -i.e. a constructor with zero parameters or with one or more parameters -all with default values in case you want to use object I/O. If do not -provide such a default constructor, you MUST implement an I/O -constructor. If not you will get a compile time error. See the "The -Default Constructor" paragraph in this chapter. The `ClassDef` and -`ClassImp` macros are defined in the file `Rtypes.h`. This file is -referenced by all ROOT include files, so you will automatically get them -if you use a ROOT include file. - -### Template Support - - -In ROOT version 3.03 and older, ROOT provided special `ClassDef` and -`ClassImp` macros for classes with two and three template arguments. In -ROOT version 3.04 and above, the macros `ClassDef` and `ClassImp` can be -used directly even for a class template. `ClassImp` is used to register -an implementation file in a class. For class templates, the `ClassImp` -can only be used for a specific class template instance. - -``` {.cpp} -ClassImp(MyClass1); -``` - -For multiple template arguments, you will need to use an intermediary -`typedef`: - -``` {.cpp} -typedef MyClass2 myc_i_f; -ClassImp(myc_i_f); -``` - -You can also register an implementation for all instances of a class -template by using `templateClassImp`: - -``` {.cpp} -templateClassImp(MyClass3); -``` - -Here are examples of a header and a `LinkDef` file: - -``` {.cpp} -// in header file MyClass.h -template class MyClass1 { -private: - T fA; - ... -public: - ... - ClassDef(MyClass1,1) -}; -template class MyClass2 { -private: - T1 fA; - T2 fB; -public: - ... - ClassDef(MyClass2,1) -}; -template class MyClass3 { -private: - T1 fA; - T2 fB; - T3 fC; - ... -public: - ... - ClassDef(MyClass3,1) -}; -``` - -``` {.cpp} -// A LinkDef.h file with all the explicit template instances -// that will be needed at link time -#ifdef __CLING__ - -#pragma link C++ class MyClass1+; -#pragma link C++ class MyClass1+; -#pragma link C++ class MyClass2+; -#pragma link C++ class MyClass2+; -#pragma link C++ class MyClass3+; -#pragma link C++ class MyClass3+; - -#endif -``` - -## The Default Constructor - - -ROOT object I/O requires every class to have either a default -constructor or an I/O constructor. A default constructor is a -constructor with zero parameters or with one or more parameters all with -default values. An I/O constructor is a constructor with exactly one -parameter which type is a pointer to one of the type marked as an 'io -constructor type'. We will come back to this context in a few -paragraphs. This default or I/O constructor is called whenever an object -is being read from a ROOT database. Be sure that you do not allocate any -space for embedded pointer objects in this constructor. This space will -be lost (memory leak) while reading in the object. For example: - -``` {.cpp} -class T49Event : public TObject { -private: -Int_t fId; -TCollection *fTracks; -... -public: - // Error space for TList pointer will be lost -T49Event() { fId = 0; fTrack = new TList; } - // Correct default initialization of pointer -T49Event() { fId = 0; fTrack = 0; } -... -}; -``` - -The memory will be lost because during reading of the object the pointer -will be set to the object it was pointing to at the time the object was -written. Create the `fTrack` list when you need it, e.g. when you start -filling the list or in a **not-default** constructor. - -``` {.cpp} -... -if (!fTrack) fTrack = new TList; -... -``` - -The constructor actually called by the ROOT I/O can be customized by -using the rootcling pragma: - -``` {.cpp} -#pragma link C++ ioctortype UserClass; -``` - -For example, with this pragma and a class named MyClass, the ROOT I/O -will call the first of the following 3 constructors which exists and is -public: - -``` {.cpp} -MyClass(UserClass*);MyClass(TRootIOCtor*); -MyClass(); // Or a constructor with all its arguments defaulted. -``` - -When more than one pragma ioctortype is used, the first seen as -priority. For example with: - -``` {.cpp} -#pragma link C++ ioctortype UserClass1; -#pragma link C++ ioctortype UserClass2; -``` - -We look for the first existing public constructor in the following -order: - -``` {.cpp} -MyClass(UserClass1*); -MyClass(UserClass2*); -MyClass(TRootIOCtor*); -MyClass(); // Or a constructor with all its arguments defaulted. -``` - -## rootcling: The Cling Dictionary Generator - -A way in which dictionaries can be generated is via the `rootcling` -utility. This tool generates takes as input a set of headers and -generates in output the dictionary C++ code and a `pcm` file. -This latter file is fundamental for the correct functioning of the -dictionary at runtime. It should be located in the directory where -the shared library is installed in which the compiled dictionary -resides. - -NOTA BENE: the dictionaries that will be used within the same project -must have unique names. In other words, compiled object files relative -to dictionary source files cannot reside in the same library or in -two libraries loaded by the same application if the original source -files have the same name. -This loose limitation is imposed by the registration mechanism ROOT -has in place to keep track of dynamically loaded libraries. - -In the following example, we walk through the steps necessary to -generate a dictionary, I/O, and inspect member functions. Let's start -with a **`TEvent`** class, which contains a collection of **`TTracks`**. - -The `TEvent.h` header is: - -``` {.cpp} -#ifndef __TEvent__ -#define __TEvent__ -#include "TObject.h" -#include "TCollection.h" - -class TTrack; - -class TEvent : public TObject { - private: - Int_t fId; // event sequential id - Float_t fTotalMom; // total momentum - TCollection *fTracks; // collection of tracks - public: - TEvent() { fId = 0; fTotalMom = 0; fTracks = nullptr; } - TEvent(Int_t id); - ~TEvent(); - void AddTrack(TTrack *t); - Int_t GetId() const { return fId; } - Int_t GetNoTracks() const; - void Print(Option_t *opt=""); - Float_t TotalMomentum(); - - ClassDef(TEvent,1); //Simple event class -}; - -#endif -``` - -The things to notice in these header files are: - -- The usage of the `ClassDef` macro - -- The default constructors of the **`TEvent`** and **`TTrack`** - classes - -- Comments to describe the data members and the comment after the - `ClassDef` macro to describe the class - -These classes are intended for you to create an event object with a -certain id, and then add tracks to it. The track objects have a pointer -to their event. This shows that the I/O system correctly handles -circular references. - -The `TTrack.h` header is: - -``` {.cpp} -#ifndef __TTrack__ -#define __TTrack__ -#include "TObject.h" - -class TEvent; - -class TTrack : public TObject { - private: - Int_t fId; //track sequential id - TEvent *fEvent; //event to which track belongs - Float_t fPx; //x part of track momentum - Float_t fPy; //y part of track momentum - Float_t fPz; //z part of track momentum - public: - TTrack() { fId = 0; fEvent = nullptr; fPx = fPy = fPz = 0; } - TTrack(Int_t id, TEvent *ev, Float_t px,Float_t py,Float_t pz); - Float_t Momentum() const; - TEvent *GetEvent() const { return fEvent; } - void Print(Option_t *opt=""); - - ClassDef (TTrack,1); //Simple track class -}; - -#endif -``` - -Next is the implementation of these two classes. - -`TEvent.cxx`: - -``` {.cpp} -#include - -#include "TOrdCollection.h" -#include "TEvent.h" -#include "TTrack.h" - -ClassImp(TEvent) - -... -``` - -`TTrack.cxx:` - -``` {.cpp} -#include - -#include "TMath.h" -#include "TTrack.h" -#include "TEvent.h" - -ClassImp(TTrack) -... -``` - -Now using `rootcling` we can generate the dictionary file. - -``` {.cpp} -rootcling eventdict.cxx -c TEvent.h TTrack.h -``` - -Looking in the file `eventdict.cxx` we can see, the` Streamer()` -and` ShowMembers() `methods for the two classes. -`Streamer()` is used to stream an object to/from a **`TBuffer`** and -`ShowMembers()` is used by the `Dump()` and `Inspect()` methods of -**`TObject`**. Here is the `TEvent::Streamer` method: - -``` {.cpp} -void TEvent::Streamer(TBuffer &R__b) -{ - // Stream an object of class TEvent. - - UInt_t R__s, R__c; - if (R__b.IsReading()) { - Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { } - TObject::Streamer(R__b); - R__b >> fId; - R__b >> fTotalMom; - R__b >> fTracks; - R__b.CheckByteCount(R__s, R__c, TEvent::IsA()); - } else { - R__c = R__b.WriteVersion(TEvent::IsA(), kTRUE); - TObject::Streamer(R__b); - R__b << fId; - R__b << fTotalMom; - R__b << fTracks; - R__b.SetByteCount(R__c, kTRUE); - } -} -``` - -The **`TBuffer`** class overloads the `operator<<()` and `operator>>()` -for all basic types and for pointers to objects. These operators write -and read from the buffer and take care of any needed byte swapping to -make the buffer machine independent. During writing, the **`TBuffer`** -keeps track of the objects that have been written and multiple -references to the same object are replaced by an index. In addition, the -object's class information is stored. **`TEvent`** and **`TTracks`** -need manual intervention. Cut and paste the generated `Streamer()` from -the `eventdict.cxx` into the class' source file and modify as needed -(e.g. add counter for array of basic types) and disable the generation -of the `Streamer()` when using the `LinkDef.h` file for next execution -of `rootcling`. In case you do not want to read or write this class (no -I/O) you can tell `rootcling` to generate a dummy `Streamer() `by -changing this line in the source file: - -``` {.cpp} -ClassDef(TEvent,0); -``` - -If you want to prevent the generation of `Streamer()`, see the section -"Adding a Class with a Shared Library". - -### Dictionaries for STL - -Usually, headers are passed to rootcling at the command line. To generate -a dictionary for a class from the STL, e.g. - -**std::vector\**, you would normally pass the header defining -**MyClass** and **std::vector**. The latter is a compiler specific -header and cannot be passed to rootcling directly. Instead, create a -little header file that includes both headers, and pass that to -rootcling. - -Often ROOT knows where **MyClass** and the templated class (e.g. vector) -are defined, for example because the files got **\#included**. Knowing -these header files ROOT can automatically generate the dictionary for -any template combination (e.g. **vector\**) when it is needed, -by generating files starting with **AutoDict\***. You can toggle this -feature on or off at the ROOT prompt by executing **.autodict**. - -## Adding a Class with a Shared Library - -\index{adding a class!shared library} -**Step 1:** Define your own class in `SClass.h` and implement it in -`SClass.cxx`. You must provide a default constructor or an I/O -constructor for your class. See the "The Default Constructor" paragraph -in this chapter. - -``` {.cpp} -#include -#include "TObject.h" -class SClass : public TObject { - private: - Float_t fX; ///>` operator overloads, are implemented only if you use `ClassDef` and -`ClassImp`. See `$ROOTSYS/include/Rtypes.h` for the definition of -`ClassDef` and `ClassImp`. To exclude a data member from the `Streamer`, -add a `!` as the first character in the comments of the field: - -``` {.cpp} -Int_t fTempValue; ///>(`**`TBuffer`** `&b,MyClass *&obj)` method for this - class. This is necessary to be able to write pointers to objects of - classes not inheriting from **`TObject`**. - -``` {.cpp} -#pragma link C++ class SClass!; // no >> operator -// or -#pragma link C++ class SClass-!; // no streamer, no >> operator -``` - -- **+** : in ROOT version 1 and 2 tells `rootcling` to generate a - `Streamer` with extra byte count information. This adds an integer - to each object in the output buffer, but it allows for powerful - error correction in case a `Streamer` method is out of sync with - data in the file. The `+` option is mutual exclusive with both the - `-` and `!` options. - -IMPORTANT NOTE: In ROOT Version 3 and later, a "+" after the class name -tells `rootcling` to use the new I/O system. The byte count check is -always added. The new I/O system has many advantages including support -automatic schema evolution, full support for STL collections and better -run-time performance. We strongly recommend using it. - -``` {.cpp} -#pragma link C++ class SClass+; // add byte count -``` - -For information on `Streamers` see "Input/Output". To get help on -`rootcling` type on the UNIX command line: **`rootcling -h`** - -#### The Order Matters - -When using template classes, the order of the pragma statements matters. -For example, here is a template class `Tmpl` and a normal class `Norm`, -which holds a specialized instance of a `Tmpl`: - -``` {.cpp} -class Norm { -private: - Tmpl* fIntTmpl; -public: - ... -}; -``` - -Then in `Linkdef.h,` the pragma statements must be ordered by listing -all specializations before any classes that need them: - -``` {.cpp} -// Correct Linkdef.h ordering -... -#pragma link C++ class Tmpl; -#pragma link C++ class Norm; -... -``` - -And not vice versa: - -``` {.cpp} -// Bad Linkdef.h ordering -... -#pragma link C++ class Norm; -#pragma link C++ class Tmpl; -... -``` - -In this case, `rootcling` generates `Norm::Streamer()` that makes -reference to `Tmpl::Streamer()`. Then `rootcling` gets to process -`Tmpl` and generates a specialized `Tmpl::Streamer()` -function. The problem is, when the compiler finds the first -`Tmpl::Streamer()`, it will instantiate it. However, later in the -file it finds the specialized version that `rootcling` generated. This -causes the error. However, if the `Linkdef.h` order is reversed then -`rootcling` can generate the specialized `Tmpl::Streamer()` before -it is needed (and thus never instantiated by the compiler). - -#### Other Useful Pragma Statements - -The complete list of pragma statements currently supported by Cling is: - -``` {.cpp} -#pragma link [C|C++|off] all [class|function|global|typedef]; -#pragma link [C|C++|off] - [class|struct|union|enum|namespace|protected][name]; -#pragma link [C|C++|off] [global|typedef][name]; -#pragma link [C|C++|off] [nestedclass|nestedtypedef]; - -#pragma link [C++|C|off|MACRO] function [name]<(argtypes)>; -#pragma link - [C++|C|off|MACRO] function [classname]::[name]<(argtypes)>; -#pragma link off all methods; -#pragma link [C|C++|off] defined_in [filename]; -#pragma link - [C|C++|off] defined_in [class|struct|namespace] [name]; -#pragma link [C|C++|off] all_function [classname]; -#pragma link [C|C++|off] all_datamember [classname]; -``` - -The `[classname]` and the `[name]` can also contain wildcards. For -example: - -``` {.cpp} -#pragma link C++ class MyClass*; -``` - -This will request the dictionary for all the class whose name start with -`'MyClass'` and are already known to Cling (class templates need to have -already been instantiated to be considered). - -``` {.cpp} -#pragma link [C|C++|off] all [class|function|global|typedef]; -``` - -This pragma statement turns on or off the dictionary generation for all -classes, structures, namespaces, global variables, global functions and -typedefs seen so far by Cling. Example: - -``` {.cpp} -// some C++ header definition -#ifdef __ROOTCLING__ -// turns off dictionary generation for all -#pragma link off all class; -#pragma link off all function; -#pragma link off all global; -#pragma link off all typedef; -#endif -``` - -The next pragma statement selectively turns on or off the dictionary -generation for the specified `classs`, `struct`, `union`, `enum` or -`namespace`: - -``` {.cpp} -#pragma link -[C|C++|off][class|class+protected| -struct|union|enum|namespace][name]; -``` - -The Dictionary of all public members of class and struct will be -generated. If the '`class+protected`' flag is used, the dictionary for -protected members will also be generated. However, dictionary for -protected constructor and destructor will not be generated. This ' -`class+protected` ' flag will help you only for plain protected member -access, but not for virtual function resolution. - -If you use the '`namespace`' flag, it is recommended to add also: - -``` {.cpp} -#pragma link C++ nestedclass; -#pragma link C++ nestedtypedef; -``` - -The behavior of '`class`', '`struct`' and '`namespace`' flag are -identical. Example: - -``` {.cpp} -// some C++ header definition -#ifdef __ROOTCLING__ -#pragma link off all class; -#pragma link C++ class A; -#pragma link C++ class B; -#pragma link C++ class C; -#pragma link C++ class+protected D; -#pragma link C++ namespace project1; -#pragma link C++ nestedclass; -#pragma link C++ nestedtypedef; -#endif -``` - -The next pragma statement selectively turns on or off the dictionary -generation for global variables and typedef. - -``` {.cpp} -#pragma link [C|C++|off] [global|typedef] [name]; -``` - -Example: - -``` {.cpp} -// some C/C++ header definition -#ifdef __ROOTCLING__ -#pragma link off all global; -#pragma link off all typedef; -#pragma link C++ global a; -#pragma link C++ typedef Int_t; -#endif -``` - -This pragma statement turns on the dictionary generation for nested -classes and nested typedefs. - -``` {.cpp} -#pragma link [C|C++|off] [nestedclass|nestedtypedef]; -``` - -Example: - -``` {.cpp} -// some C/C++ header definition -#ifdef __ROOTCLING__ -#pragma link off all global; -#pragma link off all typedef; -#pragma link C++ global a; -#pragma link C++ typedef Int_t; -#endif -``` - -The next pragma statements turn on or off the dictionary generation for -the specified function(s) or member function(s). The list of arguments' -type is optional. If you omit argument types, all function with -specified [`name`] will be affected. If the list of arguments' type is -specified, only the function that has exactly same argument list will be -affected. - -``` {.cpp} -#pragma link [C++|C|off|MACRO] function [fname]<(argtypes)>; -#pragma link -[C++|C|off|MACRO] function [classname]::[fname]<(argtypes)>; -``` - -The '`#pragma link [C++|C] function`' and -'`#pragma link MACRO function`' behaves similarly. The -'`#pragma link [C++|C] function`' assumes the target to be a real -function which has pointer to it. A pointer to registered function is -registered. On the other hand, '`#pragma link MACRO function`' assumes -target to be macro function. Pointer to function cannot be referenced in -this case. - -For the next example: - -``` {.cpp} -void f(int a); -void f(double a); -int g(int a,double b); -int g(double x); -#define max(a,b) (a>b?a:b) - -class A { - public: - int h(double y); - int h(int a,double b); -}; -``` - -The pragma statements are: - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link off all functions; -#pragma link C++ function f; -#pragma link C++ function g(int,double); -#pragma link C++ MACRO max; -#pragma link C++ class A; -#pragma link off function A::h(double); -#endif -``` - -Until Cling version 5.15.60, in order to generate dictionary for a member -function, not only the member function but also the class itself has to -be turned on for the linkage. There was an inconvenience when generating -dictionary for template member function afterwards. - -From Cling v.5.15.61, a new behavior is introduced. If link for a member -function is specified, dictionary is generated even if link to the -belonging class is off. For example, if you originally have A.h as -follows: - -``` {.cpp} -// A.h -template class A { - public: - template void f(E& x) { ... } -}; -``` - -And generate dictionary for that: - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link C++ class A; -#endif -``` - -Then prepare another header file and instantiate the template member -function of A.: - -``` {.cpp} -// B.h -#include "A.h" - -class B { -... -}; -``` - -You can generate dictionary for the newly instantiated template member -function only. - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link off defined_in A.h; -#pragma link C++ function A::f(B&); -#endif -``` - -The next pragma turns off the dictionary generation of all the member -functions in all classes. - -``` {.cpp} -#pragma link off all methods; -``` - -Example: - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link off all methods; -#endif -``` - -The next pragma statements control the linking of all the member -functions or data members for a specified class. - -``` {.cpp} -#pragma link [C|C++|off] all_function [classname]; -#pragma link [C|C++|off] all_datamember [classname]; -``` - -At this moment, there should be no needs to use those statements. -Example: - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link off all_function A; -#pragma link off all_datamember A; -#endif -``` - -See also: `#pragma link function`. - -The next pragma statement turns on/off dictionary generation of the -object defined in specific file. The filename has to be the full -pathname of the file. - -``` {.cpp} -#pragma link [C|C++|off] defined_in [filename]; -``` - -Example: - -``` {.cpp} -// file1.h -// any C++ header definition - -// file2.h - -#ifdef __ROOTCLING__ -#pragma link off all classes; -#pragma link off all functions; -#pragma link off all globals; - -#pragma link off all typedef; -#pragma link C++ defined_in file1.h; -#endif -``` - -The next pragma statements turn on or off the dictionary generation of -the object defined in a specific scope. The [`scope_name`] should be -`class` name, `struct` name or `namespace` name. When using these -pragmas, it is recommended to use also: - -``` {.cpp} -#pragma link C++ nestedclass -``` - -Otherwise, definitions in enclosed scope do not appear in the -dictionary. - -``` {.cpp} -#pragma link [C|C++|off] defined_in [scope_name]; -#pragma link [C|C++|off] defined_in -[class|struct|namespace] [scope_name]; -``` - -Example: - -``` {.cpp} -namespace ns { - int a; - double b; -}; -``` - -The pragma statements are: - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link C++ defined_in ns; -#pragma link C++ nestedclass; -#endif -``` - -This statements controls default link mode for `rootcling`. - -``` {.cpp} -#pragma link default [on|off] -``` - -By turning default 'on', all language constructs in given header files -will be included in generated Cling dictionary (interface method source -file). If default is set to 'off', nothing will be included in the -generated dictionary. The next statement explicitly set linkage to each -item: - -``` {.cpp} -#pragma link [C|C++|off] [class|function|global] -``` - -This pragma statement must be given before `rootcling` reads any -C/C++ definitions from header files. Example: - -``` {.cpp} -#ifdef __ROOTCLING__ -#pragma link default off; -#endif - -class A { - int a; - double b; -}; - -class B { - int d; - double e; -}; - -#ifdef __ROOTCLING__ -#pragma link C++ class A; // only class A is linked, not B -#endif -``` - -##### Compilation - -**Step 4:** Compile the class using the `Makefile. `In the `Makefile` -call `rootcling` to make the dictionary for the class. Call it -`SClassDict.cxx`. The `rootcling` utility generates the methods -`Streamer`, **`TBuffer`** &operator\>\>() and `ShowMembers `for ROOT -classes. - -``` {.cpp} -gmake -f Makefile -``` - -Load the shared library: - -``` {.cpp} -root[] .L SClass.so -root[] SClass *sc = new SClass() -root[] TFile *f = new TFile("Afile.root","UPDATE"); -root[] sc->Write(); -``` - -For more information on `rootcling` see the `$ROOTSYS/test` directory -`Makefile`, `Event.cxx`, and `Event.h` for an example, or follow this -link: - -## genreflex: A Comfortable Interface to rootcling - -Version 5 supported both `Cint` and `Reflex` dictionaries. The tool to create -`Reflex` dictionaries was a Python script called `genreflex` and was very -successful in the user community. -Even if version 6 has only one type of dictionaries, `cling` dictionaries, -a re-implementation of `genreflex` is provided. -More precisely, in ROOT6, `genreflex` is nothing but a wrapper around -`rootcling`, which offers an identical CLI and behaviour to the old Python -tool. -The input to `genreflex` is a C++ header file, a set of switches and a -*selection XML file*. The output, as for `rootcling`, is a C++ dictionary -source and a `pcm` files. -An exhaustive documentation of the CLI switches of `genreflex` can be -inspected with the `genreflex --help` command. - -The entity corresponding to the `LinkDef` file for `genreflex` is the -*selection XML file*, also called *selection XML* or simply *selection file*. -A *selection XML file* allows to describe a list of classes for which -the dictionaries are to be created. In addition, it allows to specify -properties of classes or data members, without the need to add comments in -the source code. This is of primary importance when dictionaries must be -created for classes residing in code which cannot be modified. -For a complete description of the structure of the *selection XML files* -and the way in which attributes can be set, refer to the `genreflex --help` -command. - -It is important to observe that *selection XML files* can be used in presence -of `rootcling` invocations instead of `LinkDef` files. - -### The `ROOT::Meta::Selection` namespace - -Not only `LinkDef` and `selection` files allow to select the classes for which -the dictionaries must be created: a third method is available. This is -represented by the `ROOT::Meta::Selection` namespace. The idea behind this -technique is that all the classes which are located in this special namespace -are automatically selected for dictionary generation. All the properties and -annotations allowed by `LinkDef` and `selection XML` files are possible. -For a detailed documentation of the features of the `ROOT::Meta::Selection` -namespace, refer to its online documentation. - -## Adding a Class with ACLiC - -\index{adding a class!ACLiC} -**Step 1:** Define your class - -``` {.cpp} -#include "TObject.h" - -// define the ABC class and make it inherit from TObject so that -// we can write ABC to a ROOT file -class ABC : public TObject { - - public: - Float_t a, b, c, p; - ABC() : a(0), b(0), c(0), p(0){}; - -// Define the class for the dictionary - ClassDef (ABC,1) -}; - -// Call the ClassImp macro to give the ABC class RTTI and -// full I/O capabilities. - -#if !defined(__CLING__) -ClassImp(ABC); -#endif -``` - -**Step 2:** Load the ABC class in the script. - -``` {.cpp} - // Check if ABC is already loaded - if (!TClass::GetDict("ABC")) { - gROOT->ProcessLine(".L ABCClass.C++"); - } - - // Use the Class - ABC *v = new ABC; - v->p = (sqrt((v->a * v->a)+ (v->b * v->b)+(v->c * v->c))); -``` diff --git a/documentation/users-guide/Cling.md b/documentation/users-guide/Cling.md deleted file mode 100644 index dbe958d70f6b4..0000000000000 --- a/documentation/users-guide/Cling.md +++ /dev/null @@ -1,757 +0,0 @@ -# The C++ Interpreter Cling -\index{cling} - -ROOT has a C++ interpreter called *cling* built in. It is used for the prompt, both C++ and -Python. It also serves as a source of information to store C++ objects, and -provides the back-end for ROOT's signal/slot and plug-in mechanisms. - -This chapter focuses on the parts of *cling* that you will encounter while -interacting with ROOT. - -## The ROOT Prompt - - -Start up a ROOT session by typing `root` at the system prompt. - -``` {.cpp} -$ root - ------------------------------------------------------------------------- - | Welcome to ROOT 6.10/01 http://root.cern.ch | - | (c) 1995-2017, The ROOT Team | - | Built for macosx64 | - | From heads/v6-10-00-patches@v6-10-00-25-g9f78c3a, Jul 03 2017, 11:39:44 | - | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' | - ------------------------------------------------------------------------- - -root [0] -``` - -Now we create a `TLine` object: - -``` {.cpp} -root [1] TLine l; -root [2] l.Print() -TLine X1=0.000000 Y1=0.000000 X2=0.000000 Y2=0.000000 -root [3] l.SetX1(10) -root [4] l.SetY1(11) -root [5] l.Print() -TLine X1=10.000000 Y1=11.000000 X2=0.000000 Y2=0.000000 -root [6] .g l -.g l -ROOT_prompt_0 1 (address: NA) class TLine l, size = 72 -root [7] l.GetX1(); -root [8] l.GetX1() -(Double_t) 1.000000e+01 -``` - -Note some of the features of the ROOT prompt: -- Terminating with ‘`;`‘ is not required, see "C++ Extensions To Ease -Scripting" below. -- `Emacs` style command line editing. -- Raw interpreter commands start with a dot; `.g l` for instance shows the -interpreter information on the global called `l`. -- To show the result of an expression just do not type the trailing `;`. - -For the further examples we will "abbreviate" `root [0]` etc by `root []`. - -``` {.cpp} -root [] .class TLine -=========================================================================== -class TLine -SIZE: 72 FILE: TLine.h LINE: 39 -Base classes: -------------------------------------------------------- -0x20 public TAttBBox2D -List of member variables -------------------------------------------------- -TLine.h 42 0x28 protected: Double_t fX1 -TLine.h 43 0x30 protected: Double_t fY1 -TLine.h 44 0x38 protected: Double_t fX2 -TLine.h 45 0x40 protected: Double_t fY2 -TLine.h 50 0x0 public: enum TLine:: kLineNDC -TLine.h 51 0x0 public: enum TLine:: kVertical -TLine.h 52 0x0 public: enum TLine:: kHorizontal -TLine.h 94 0x0 private: static class TClass *fgIsA -List of member functions :--------------------------------------------------- -filename line:size busy function type and name -(compiled) (NA):(NA) 0 public: TLine(); -(compiled) (NA):(NA) 0 public: TLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2); -(compiled) (NA):(NA) 0 public: TLine(const TLine &line); -(compiled) (NA):(NA) 0 public: virtual ~TLine() noexcept; -(compiled) (NA):(NA) 0 public: void Copy(class TObject &line) const; -(compiled) (NA):(NA) 0 public: virtual Int_t DistancetoPrimitive(Int_t px, Int_t py); -(compiled) (NA):(NA) 0 public: virtual class TLine *DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2); -(compiled) (NA):(NA) 0 public: virtual class TLine *DrawLineNDC(Double_t x1, Double_t y1, Double_t x2, Double_t y2); -(compiled) (NA):(NA) 0 public: virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py); -(compiled) (NA):(NA) 0 public: Double_t GetX1() const; -(compiled) (NA):(NA) 0 public: Double_t GetX2() const; -(compiled) (NA):(NA) 0 public: Double_t GetY1() const; -(compiled) (NA):(NA) 0 public: Double_t GetY2() const; -(compiled) (NA):(NA) 0 public: Bool_t IsHorizontal(); -(compiled) (NA):(NA) 0 public: Bool_t IsVertical(); -(compiled) (NA):(NA) 0 public: virtual void ls(Option_t *option = "") const; -(compiled) (NA):(NA) 0 public: virtual void Paint(Option_t *option = ""); -(compiled) (NA):(NA) 0 public: virtual void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2); -(compiled) (NA):(NA) 0 public: virtual void PaintLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2); -(compiled) (NA):(NA) 0 public: virtual void Print(Option_t *option = "") const; -(compiled) (NA):(NA) 0 public: virtual void SavePrimitive(std::ostream &out, Option_t *option = ""); -(compiled) (NA):(NA) 0 public: virtual void SetNDC(Bool_t isNDC = kTRUE); -(compiled) (NA):(NA) 0 public: void SetHorizontal(Bool_t set = kTRUE); -(compiled) (NA):(NA) 0 public: void SetVertical(Bool_t set = kTRUE); -(compiled) (NA):(NA) 0 public: virtual void SetX1(Double_t x1); -(compiled) (NA):(NA) 0 public: virtual void SetX2(Double_t x2); -(compiled) (NA):(NA) 0 public: virtual void SetY1(Double_t y1); -(compiled) (NA):(NA) 0 public: virtual void SetY2(Double_t y2); -(compiled) (NA):(NA) 0 public: virtual struct Rectangle_t GetBBox(); -(compiled) (NA):(NA) 0 public: virtual class TPoint GetBBoxCenter(); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxCenter(const class TPoint &p); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxCenterX(const Int_t x); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxCenterY(const Int_t y); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxX1(const Int_t x); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxX2(const Int_t x); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxY1(const Int_t y); -(compiled) (NA):(NA) 0 public: virtual void SetBBoxY2(const Int_t y); -(compiled) (NA):(NA) 0 public: static class TClass *Class(); -(compiled) (NA):(NA) 0 public: static const char *Class_Name(); -(compiled) (NA):(NA) 0 public: static Version_t Class_Version(); -(compiled) (NA):(NA) 0 public: static void Dictionary(); -(compiled) (NA):(NA) 0 public: virtual class TClass *IsA() const; -(compiled) (NA):(NA) 0 public: virtual void ShowMembers(class TMemberInspector &insp) const; -(compiled) (NA):(NA) 0 public: virtual void Streamer(class TBuffer &); -(compiled) (NA):(NA) 0 public: void StreamerNVirtual(class TBuffer &ClassDef_StreamerNVirtual_b); -(compiled) (NA):(NA) 0 public: static const char *DeclFileName(); -(compiled) (NA):(NA) 0 public: static int ImplFileLine(); -(compiled) (NA):(NA) 0 public: static const char *ImplFileName(); -(compiled) (NA):(NA) 0 public: static int DeclFileLine(); -root [] .> test.log -root [] l.Dump(); -root [] .> -root [] ? -``` - -Here we see: - -- Use `.class` as quick help and reference -- Unix like I/O redirection using `.> out.txt` and unredirection with `.>` -- Use `?` to get help on all ‘‘raw'' interpreter commands -- Use @ to abort a multi-line command - -Now let us execute a multi-line command: - -``` {.cpp} -root [] { -root [] ? TLine l; -root [] ? for (int i = 0; i < 5; i++) { -root [] ? l.SetX1(i); -root [] ? l.SetY1(i+1); -root [] ? l.Print(); -root [] ? } -root [] ? } -TLine X1=0.000000 Y1=1.000000 X2=0.000000 Y2=0.000000 -TLine X1=1.000000 Y1=2.000000 X2=0.000000 Y2=0.000000 -TLine X1=2.000000 Y1=3.000000 X2=0.000000 Y2=0.000000 -TLine X1=3.000000 Y1=4.000000 X2=0.000000 Y2=0.000000 -TLine X1=4.000000 Y1=5.000000 X2=0.000000 Y2=0.000000 -root [] .q -``` - -Here we note: - -- A multi-line command starts with a { and ends with a }. -- Inside continuation, every line has to be correctly terminated with a ; (like in "real'' - C++). -- All objects are created in *global* scope. -- There is no way to back up; you are better off writing a script. -- Use `.q` to exit root. - - - -## Feeding Sources Files To ROOT: C++ Scripts - - -ROOT script files (often called "Macros") contain pure C++ code. They can contain a simple -sequence of statements like in the multi command line example given -above, but also arbitrarily complex class and function definitions. - -The most frequent interaction with the ROOT prompt uses `.x` to "run" a file: - -``` -root [] .x myScript.C -``` - -This loads myScript.C into the interpreter and calls the function `myScript()`. -You can pass arguments using `.x myScript.C(12, "A String")`. - -Alternatively you can load the script and then run a function explicitly: - -``` -root [] .L myScript.C -root [] myScript() -``` - -The above is equivalent to `.x myScript.C`. - -In a named script, the objects created on the stack are deleted when -the function exits. In a common scenario you -create a histogram in a named script on the stack. You draw the -histogram, but when the function exits the canvas is empty and the -histogram has disappeared. To avoid the histogram from disappearing you can -create it on the heap (by using new). This will leave the histogram -object intact, but the pointer in the named script scope will be -"gone". Since histograms (and trees) are added to the list of objects -in the current directory, you can always retrieve them to delete them -if needed. - -``` {.cpp} -root[] TH1F *h = (TH1F*)gDirectory->Get("myHist"); // or -root[] TH1F *h = (TH1F*)gDirectory->GetList()->FindObject("myHist"); -``` - -In addition, histograms and trees are automatically deleted when the -current directory is closed. This will automatically take care of the -clean up. See "Input/Output". - - - - -### Executing a Script From a Script - - -You may want to execute a script conditionally inside another script. -To do it you need to call the interpreter and you can do that with -`TROOT::ProcessLine()`. The example -`$ROOTSYS/tutorials/io/tree/tree500_cernstaff.C` calls a script to build the root -file if it does not exist: - -``` {.cpp} -void cernstaff() { - if (gSystem->AccessPathName("cernstaff.root")) { - gROOT->ProcessLine(".x cernbuild.C"); - } -``` - -`ProcessLine` takes a parameter, which is a pointer to an `int` or to -a `TInterpreter::EErrorCode` to let you access the interpreter error -code after an attempt to interpret. This will contain the error -as defined in `enum TInterpreter::EErrorCode` with `TInterpreter::kSuccess` being -the value for a successful execution. - - - -### Executing a Script From the Invocation - - -Instead if starting ROOT and running a script on the prompt you can also pass -it to ROOT in its invocation: - -``` -$ root -l -b 'myCode.C("some String", 12)' -``` - -The exact kind of quoting depends on your shell; the one shown here works for -bash-like shells. - -ROOT can evaluate any expression as part of the invocation; another version of -the previous example can be spelled like this: - -``` -$ root -l -b -e 'gROOT->ProcessLine(".x myCode.C(\"some String\", 12)");' -``` - - - -## C++ Extensions To Ease Scripting - -In the next example, we demonstrate three of the most important -extensions ROOT and Cling make to C++. Start ROOT in the directory -`$ROOTSYS/tutorials` (make sure to have first run `.x hsimple.C`): - -``` {.cpp} -root [0] f = new TFile("hsimple.root") -(class TFile *) 0x4045e690 -root [1] f->ls() -TFile** hsimple.root -TFile* hsimple.root -KEY: TH1F hpx;1 This is the px distribution -KEY: TH2F hpxpy;1 py ps px -KEY: THProfile hprof;1 Profile of pz versus px -KEY: TNtuple ntuple;1 Demo ntuple -root [2] hpx->Draw() -Warning in : creating a default canvas with name c1 -root [3] .q -``` - -The `root [0]` command shows the first extension; the declaration of `f` -may be omitted as a shortcut for `auto`. Cling will correctly -create `f` as pointer to object of class `TFile`. Nonetheless we recommend -to use `auto f = new TFile("hsimple.root")`. - -The second extension is more important. In case Cling cannot find an -object being referenced, it will ask ROOT to search for an object with -an identical name in the search path defined by `TROOT::FindObject()`. -If ROOT finds the object, it returns a pointer to this object to Cling and -a pointer to its class definition and Cling will execute the requested -member function. This shortcut is quite natural for an interactive -system and saves much typing. In this example, ROOT searches for `hpx` -and finds it in `hsimple.root.` - -The next, fundamental extension is shown below. There is no need to put a semicolon at -the end of a line. When you leave it off the value of the expression will -be printed on the next line. For example: - -``` {.cpp} -root[] 23+5 -(int)28 -root[] 23+5; -root[] TMath::Sin -(Double_t (*)(Double_t)) Function @0x7ffff7ebb090 - at include/TMath.h:418: -inline Double_t TMath::Sin(Double_t x) - { return sin(x); } -``` - -Be aware that these extensions do not work when a compiler replaces -the interpreter. Your code will not compile, hence when writing large -scripts, it is best to stay away from these shortcuts. It will save -you from having problems compiling your scripts using a real C++ -compiler. - - - -## ACLiC: Compiling Scripts Into Libraries - - - -Instead of having Cling interpret your script there is a way to have your -scripts compiled, linked and dynamically loaded using the C++ compiler -and linker. The advantage of this is that your scripts will run with the -speed of compiled C++ and that you can use language constructs that are -not fully supported by Cling. On the other hand, you cannot use any Cling -shortcuts (see "C++ Extensions To Ease Scripting" above) and for small scripts, the -overhead of the compile/link cycle might be larger than just executing -the script in the interpreter. - -ACLiC will build a dictionary and a shared library from your C++ -script, using the compiler and the compiler options that were used to -compile the ROOT executable. You do not have to write a Makefile -remembering the correct compiler options, and you do not have to exit -ROOT. - -### Usage - - -Before you can compile your interpreted script you need to add include -statements for the classes used in the script. Once you did that, you -can build and load a shared library containing your script. To load it -use the command `.L` and append the file name with a `+`. - -``` {.cpp} -root[] .L MyScript.C+ -``` - -The + option generates the shared library and names it by taking -the name of the file "filename" but replacing the dot before the -extension by an underscore and by adding the shared library extension -for the current platform. For example on most platforms, `hsimple.cxx` -will generate `hsimple_cxx.so`. - -The + command rebuild the library only if the script or any of the -files it includes are newer than the library. When checking the -timestamp, ACLiC generates a dependency file which name is the same as -the library name, just replacing the 'so' extension by the extension -'d'. For example on most platforms, `hsimple.cxx` will generate -`hsimple_cxx.d`. - -To ensure that the shared library is rebuilt you can use the ++ -syntax: - -``` {.cpp} -root[] .L MyScript.C++ -``` - -To build, load, and execute the function with the same name as the -file you can use the `.x` command. This is the same as executing a -named script; you can also provide parameters. The only -difference is you need to append a + or a ++. - -``` {.cpp} -root[] .x MyScript.C+(4000) -Creating shared library /home/./MyScript_C.so -``` - -You can select whether the script in compiled with debug symbol or -with optimization by appending the letter 'g' or 'O' after the '+' or -'++'. Without the specification, the script is compiled with the same -level of debugging symbol and optimization as the currently running -ROOT executable. For example: - -``` {.cpp} -root[] .L MyScript.C++g -``` - -will compile `MyScript.C` with debug symbols; usually this means -giving the `-g` option to compiler. - -``` {.cpp} -root[] .L MyScript.C++O -``` - -will compile `MyScript.C` with optimizations; usually this means -giving the `-O` option to compiler. The syntax: - -``` {.cpp} -root[] .L MyScript.C++ -``` - -is using the default optimization level. The initial default is to -compile with the same level of optimization as the root executable -itself. The default can be changed by: - -``` {.cpp} -root[] gSystem->SetAclicMode(TSystem::kDebug); -root[] gSystem->SetAclicMode(TSystem::kOpt); -``` - -Note that the commands: - -``` {.cpp} -root[] .L MyScript.C+g -root[] .L MyScript.C+O -``` - -respectively compile `MyScript.C` with debug and optimization if the -library does not exist yet; they will not change the debug and the -optimization level if the library already exist and it is up to date. -To use ACLiC from compiled code or from inside another macro, we -recommend using `gROOT->ProcessLine()`. For -example, in one script you can use ACLiC to compile and load another -script. - -``` {.cpp} -gROOT->ProcessLine(".L MyScript.C+") -gROOT->ProcessLine(".L MyScript.C++") -``` - -### Setting the Include Path - - -You can get the include path by typing: - -``` {.cpp} -root[] .include -``` - -You can append to the include path by typing: - -``` {.cpp} -root[] .include $HOME/mypackage/include -``` - -In a script you can append to the include path: - -``` {.cpp} -gSystem->AddIncludePath(" -I$HOME/mypackage/include ") -``` - -You can also overwrite the existing include path: - -``` {.cpp} -gSystem->SetIncludePath(" -I$HOME/mypackage/include ") -``` - -The `$ROOTSYS/include` directory is automatically appended to the -include path, so you do not have to worry about including it. To add -library that should be used during linking of the shared library use -something like: - -``` {.cpp} -gSystem->AddLinkedLibs("-L/my/path -lanylib"); -``` - -This is especially useful for static libraries. For shared ones you -can also simply load them before trying to compile the script: - -``` {.cpp} -gSystem->Load("mydir/mylib"); -``` - -ACLiC uses the directive `fMakeSharedLibs` to create the shared -library. If loading the shared library fails, it tries to output a -list of missing symbols by creating an executable (on some platforms -like OSF, this does not HAVE to be an executable) containing the -script. It uses the directive `fMakeExe` to do so. For both -directives, before passing them to `TSystem::Exec()`, it expands the -variables `$SourceFiles`, `$SharedLib`, `$LibName`, `$IncludePath`, -`$LinkedLibs`, `$ExeName `and` $ObjectFiles`. See `SetMakeSharedLib()` -for more information on those variables. When the file being passed to -ACLiC is on a read only file system, ACLiC warns the user and creates -the library in a temporary directory: - -``` {.cpp} -root[] .L readonly/t.C++ -Warning in : /scratch/aclic/subs/./readonly is not writable! -Warning in : Output will be written to /tmp -Info in : creating shared library -/tmp//scratch/aclic/subs/./readonly/t_C.so -``` - -To select the temporary directory ACLiC looks at `$TEMP`, `$TEMP_DIR`, -`$TEMPDIR`, `$TMP`, `$TMPDIR`, `$TMP_DIR `or uses `/tmp (`or `C:/)`. -Also, a new interface `TSystem::Get/SetBuildDir` is introduced -to let users select an alternative 'root' for building of the ACLiC -libraries. For `filename/full/path/name/macro.C`, the library is -created as `fBuildDir/full/path/name/macro_C.so.` - -### Dictionary Generation - - -You can direct what is added to the dictionary generated by ACLiC in -two ways. The simplest way is to add at the end of script (i.e. after -the symbols have been defined) something like: - -``` {.cpp} -#if defined(__ROOTCLING__) -#pragma link C++ class MyOtherClass; -#endif -``` - -You can also write this portion of code in a file name -`MyScript_linkdef.h` where the suffix `'_linkdef' `is the prefix -defined by the key `‘ACLiC.Linkdef`‘ in the currently used resource -file (usually `.rootrc `or` $ROOTSYS/etc/system.rootrc`) and the -prefix is the name of your script. - -The default behavior of `rootcling` is to -not link in (i.e. generate the dictionary for) any of the symbols. In -particular, this means that the following lines are, in the -general case, unnecessary. - -``` {.cpp} -#pragma link off all globals; -#pragma link off all classes; -#pragma link off all functions; -``` - -This also means that linking the instantiation of a class template: - -``` {.cpp} -#pragma link C++ class mytemplate; -``` - -ONLY links this specific class. You need to -request the generation of the iterators explicitly. - -See the documentation of `rootcling` for details how `pragma` can be -used. - -NOTE: You should not call ACLiC with a script that has a function -called `main()`. - -### Intermediate Steps and Files - - -ACLiC executes two steps and a third one if needed. These are: - -- Calling `rootcling` to create a dictionary using `rootcling`. -- Calling the compiler to build the shared library from the script. -- If there are errors, it calls the compiler to build a dummy - executable to clearly report unresolved symbols. - -ACLiC makes a shared library with a dictionary containing the -classes and functions declared in the script. It also adds the -classes and functions declared in included files with the same name -as the script file and any of the following extensions: `.h`, `.hh`, -`.hpp`, `.hxx`, `.hPP`, `.hXX`. This means that, by default, you -cannot combine scripts from different files into one library by using -`#include` statements; you will need to compile each script -separately. In a future release, we plan to add the global variables -declared in the script to the dictionary also. If you are curious -about the specific calls, you can raise the ROOT debug level: gDebug=3 -and ACLiC will print these steps. If you need to keep the intermediate -files around, for example when debugging the script using gdb, use -gDebug=7. - -### Moving between Interpreter and Compiler - - -The best way to develop portable scripts is to make sure you can -always run them with both, the interpreter and with ACLiC. To do so, -do not use the Cling extensions and program around the Cling -limitations. When it is not possible or desirable to program around -the Cling limitations, you can use the C preprocessor symbols defined -for Cling and `rootcling`. - -The preprocessor symbol `__CLING__` is defined for both ROOT and -`rootcling`. The symbol `__ROOTCLING__` (and `__MAKECINT__` for backward -compatibility) is only defined in `rootcling`. - -Use `!defined(__CLING__) || defined(__ROOTCLING__)` to bracket code that -needs to be seen by the compiler and `rootcling`, but will be invisible -to the interpreter. - -Use `!defined(__CLING__) `to bracket code that should be seen only by -the compiler and not by Cling nor `rootcling. `For example, the following -will hide the declaration and initialization of the array `gArray` -from both Cling and `rootcling`. - -``` {.cpp} -#if !defined(__CLING__) -int gArray[] = { 2, 3, 4}; -#endif -``` - -Because ACLiC calls `rootcling` to build a dictionary, the declaration -of `gArray` will not be included in the dictionary, and consequently, -`gArray` will not be available at the command line even if ACLiC is -used. Cling and `rootcling` will ignore all statements between the -`"#if !defined` `(__CLING__)"` and "`#endif"`. If you want to use -`gArray` in the same script as its declaration, you can do so. -However, if you want use the script in the interpreter you have to -bracket the usage of `gArray` between `#if's,` since the definition is -not visible. If you add the following preprocessor statements: - -``` {.cpp} -#if !defined(__CLING__) -int gArray[] = { 2, 3, 4}; -#elif defined(__ROOTCLING__) -int gArray[]; -#endif -``` - -`gArray` will be visible to `rootcling` but still not visible to Cling. -If you use ACLiC, `gArray` will be available at the command line and -be initialized properly by the compiled code. - -We recommend you always write scripts with the needed include -statements. In most cases, the script will still run with the -interpreter. However, a few header files are not handled very well by -Cling. - -These types of headers can be included in interpreted and compiled -mode: - -- The subset of standard C/C++ headers defined in - `$ROOTSYS/Cling/include.` - -- Headers of classes defined in a previously loaded library - (including ROOT own). The defined class must have a name known to - ROOT (i.e. a class with a `ClassDef`). - -Hiding header files from `rootcling` that are necessary for the -compiler but optional for the interpreter can lead to a subtle but -fatal error. For example: - -``` {.cpp} -#ifndef __CLING__ -#include "TTree.h" -#else -class TTree; -#endif - -class subTree : public TTree { -}; -``` - -In this case, `rootcling` does not have enough information about the -`TTree` class to produce the correct dictionary file. If you try -this, `rootcling` and compiling will be error free, however, -instantiating a `subTree` object from the Cling command line will cause -a fatal error. In general, it is recommended to let `rootcling` see as -many header files as possible. - - - -## Classes Defined By Scripts - - -Lets create a small class `TMyClass` and a derived class -`TChild`. The virtual method `TMyClass::Print() `is overridden in -`TChild`. Save this in file called `script4.C`. - -``` {.cpp} -#include - -class TMyClass { - private: - float fX; //x position in centimeters - float fY; //y position in centimeters - public: - TMyClass() { fX = fY = -1; } - virtual void Print() const; - void SetX(float x) { fX = x; } - void SetY(float y) { fY = y; } -}; -void TMyClass::Print() const // parent print method -{ - cout << "fX = " << fX << ", fY = " << fY << endl; -} -class TChild : public TMyClass { - public: - void Print() const; -}; -void TChild::Print() const // child print metod -{ - cout << "This is TChild::Print()" << endl; - TMyClass::Print(); -} -``` - -To execute `script4.C` do: - -``` {.cpp} -root[] .L script4.C -root[] TMyClass *a = new TChild -root[] a->Print() -This is TChild::Print() -fX = -1, fY = -1 -root[] a->SetX(10) -root[] a->SetY(12) -root[] a->Print() -This is TChild::Print() -fX = 10, fY = 12 -root[] .class TMyClass -===================================================== -class TMyClass -size=0x8 FILE:script4.C LINE:3 -List of base class----------------------------------- -List of member variable------------------------------ -Defined in TMyClass -0x0 private: float fX -0x4 private: float fY -List of member function------------------------------ -Defined in TMyClass -filename line:size busy function type and name -script4.C 16:5 0 public: class TMyClass TMyClass(void); -script4.C 22:4 0 public: void Print(void); -script4.C 12:1 0 public: void SetX(float x); -script4.C 13:1 0 public: void SetY(float y); -root[] .q -``` - -As you can see, an interpreted class behaves just like a compiled -class. -See "Adding a Class" for ways how to add a class with a shared library -and with ACLiC. - - - -## Inspecting Objects - - -An object of a class inheriting from `TObject` can be inspected, -with the `Inspect()` method. The `TObject::Inspect` method creates a -window listing the current values of the objects members. For example, -the next picture is of `TFile`. - -``` {.cpp} -root[] TFile f("staff.root") -root[] f.Inspect() -``` - -You can see the pointers are in red and can be clicked on to follow -the pointer to the object. If you clicked on `fList`, the list of -objects in memory and there were none, no new canvas would be shown. -On top of the page are the navigation buttons to see the previous and -next screen. - -![ROOT object inspector of TFile](pictures/03000092.png) - -![The object inspector of `fKeys`, the list of keys in the memory](pictures/03000093.png) diff --git a/documentation/users-guide/CollectionClasses.md b/documentation/users-guide/CollectionClasses.md deleted file mode 100644 index 12a37be7b15af..0000000000000 --- a/documentation/users-guide/CollectionClasses.md +++ /dev/null @@ -1,584 +0,0 @@ -# Collection Classes - - -Collections are a key feature of the ROOT system. Many, if not most, of -the applications you write will use collections. If you have used -parameterized C++ collections or polymorphic collections before, some of -this material will be review. However, much of this chapter covers -aspects of collections specific to the ROOT system. When you have read -this chapter, you will know - -- How to create instances of collections - -- The difference between lists, arrays, hash tables, maps, etc. - -- How to add and remove elements of a collection - -- How to search a collection for a specific element - -- How to access and modify collection elements - -- How to iterate over a collection to access collection elements - -- How to manage memory for collections and collection elements - -- How collection elements are tested for equality (`IsEqual(`)) - -- How collection elements are compared (`Compare())` in case of sorted - collections - -- How collection elements are hashed (`Hash()`) in hash tables - -## Understanding Collections - - -A collection is a group of related objects. You will find it easier to -manage a large number of items as a collection. For example, a diagram -editor might manage a collection of points and lines. A set of widgets -for a graphical user interface can be placed in a collection. A -geometrical model can be described by collections of shapes, materials -and rotation matrices. Collections can themselves be placed in -collections. Collections act as flexible alternatives to traditional -data structures of computers science such as arrays, lists and trees. - -### General Characteristics - - -The ROOT collections are polymorphic containers that hold pointers to -`TObjects`, so: - -- They can only hold objects that inherit from **`TObject`** - -- They return pointers to `TObjects`, that have to be cast back to the - correct subclass - -Collections are dynamic; they can grow in size as required. Collections -themselves are descendants of **`TObject`** so can themselves be held in -collections. It is possible to nest one type of collection inside -another to any level to produce structures of arbitrary complexity. - -Collections do not own the objects they hold for the very good reason -that the same object could be a member of more than one collection. -Object ownership is important when it comes to deleting objects; if -nobody owns the object it could end up as wasted memory (i.e. a memory -leak) when no longer needed. If a collection is deleted, its objects are -not. The user can force a collection to delete its objects, but that is -the user's choice. - -### Determining the Class of Contained Objects - - -Most containers may hold heterogeneous collections of objects and then -it is left to the user to correctly cast the **`TObject`** pointer to -the right class. Casting to the wrong class will give wrong results and -may well crash the program! Therefore, the user has to be very careful. -Often a container only contains one class of objects, but if it really -contains a mixture, it is possible to ask each object about its class -using the `InheritsFrom` method. - -For example if `myObject` is a **`TObject`** pointer: - -``` {.cpp} -if (myObject->InheritsFrom("TParticle") { - printf("myObject is a TParticlen"); -} -``` - -As the name suggests, this test works even if the object is a subclass -of **`TParticle`**. The member function `IsA()` can be used instead of -`InheritsFrom` to make the test exact. The `InheritsFrom` and `IsA` -methods use the extensive Run Time Type Information (RTTI) available via -the ROOT meta-classes. - -### Types of Collections - - -The ROOT system implements the following basic types of collections: -unordered collections, ordered collections and sorted collections. Next -figure shows the inheritance hierarchy for the primary collection -classes. All primary collection classes derive from the abstract base -class **`TCollection`**. - -![The inheritance hierarchy of the primary collection classes](pictures/020001A3.jpg) - -### Ordered Collections (Sequences) - - -Sequences are collections that are externally ordered because they -maintain internal elements according to the order in which they were -added. The following sequences are available: - -- **`TList`** - -- **`THashList`** - -- **`TOrdCollection`** - -- **`TObjArray`** - -- **`TClonesArray`** - -The **`TOrdCollection`**, **`TObjArray`** as well as the -**`TClonesArray`** can be sorted using their Sort() member function (for -this, the stored objects must provide a comparison function by -overriding TObject::Compare() and also must enable sorting by overriding -TObject::IsSortable() to return true). Ordered collections all derive -from the abstract base class **`TSeqCollection`**. Sorted collections -are ordered by an internal (automatic) sorting mechanism. The following -sorted collections are available (the stored items must be sortable): - -- **`TSortedList`** - -- **`TBtree`** - -Unordered collections don't maintain the order in which the elements -were added, i.e. when you iterate over an unordered collection, you are -not likely to retrieve elements in the same order they were added to the -collection. The following unordered collections are available: - -- **`THashTable`** - -- **`TMap`** - -## Iterators: Processing a Collection - - -The concept of processing all the members of a collection is generic, -i.e. independent of any specific representation of a collection. To -process each object in a collection one needs some type of cursor that -is initialized and then steps over each member of the collection in -turn. Collection objects could provide this service but there is a snag: -as there is only one collection object per collection there would only -be one cursor. Instead, to permit the use of as many cursors as -required, they are made separate classes called iterator. For each -collection class there is an associated iterator class that knows how to -sequentially retrieve each member in turn. The relationship between a -collection and its iterator is very close and may require that the -iterator has full access to the collection (i.e. it is a friend class). -In general iterator will be used via the **`TIter`** wrapper class. For -example: - -- **`TList`** **`TListIter`** - -- **`TMap`** **`TMapIter`** - -## Foundation Classes - - -All collections are based on the fundamental classes: **`TCollection`** -and **`TIterator`**. They are so generic that it is not possible to -create objects from them; they are only used as base classes for other -classes (i.e. they are abstract base classes). - -The **`TCollection`** class provides the basic protocol (i.e. the -minimum set of member functions) that all collection classes have to -implement. These include: - -- `Add` `Adds another object to the collection.` - -- `GetSize` `Returns the number of objects in the collection.` - -- `Clear` - `Clears out the collection, but does not delete the removed objects.` - -- `Delete` - `Clears out the collection and deletes the removed objects. This should only ` - `be used if the collection owns its objects (which are not normally the case).` - -- `FindObject` `Finds an object given either its name or address.` - -- `MakeIterator` `Returns an iterator associated with the collection.` - -- `Remove` `Removes an object from the collection.` - -The code example below shows a class containing three lists, where the -`fTracks` list is the owning collection and the other two lists are used -to store a sub-set of the track objects. In the destructor of the class, -the method `Delete` is called for the owning collection to delete -correctly its entire track objects. To delete the objects in the -container use `fTrack->Delete()`. To delete the container itself, do -'`delete fTracks'.` - -``` {.cpp} -class TEvent : public TObject { - private: - TList *fTracks; //list of all tracks - TList *fVertex1; //subset of tracks part of vertex1 - TList *fVertex2; //subset of tracks part of vertex2 -}; -TEvent::~TEvent() -{ - fTracks->Delete(); - delete fTracks; - delete fVertex1; - delete fVertex2; -} -``` - -The **`TIterator`** class defines the minimum set of member functions -that all iterators must support. These include: - -- `Next` - `Returns the next member of the collection or 0 if no more members.` - -- `Reset` `Resets the iterator so that ` `Next` - ` returns the first object.` - -## A Collectable Class - - -By default, all objects of **`TObject`** derived classes can be stored -in ROOT containers. However, the **`TObject`** class provides some -member functions that allow you to tune the behavior of objects in -containers. For example, by default two objects are considered equal if -their pointers point to the same address. This might be too strict for -some classes where equality is already achieved if some or all of the -data members are equal. By overriding the following **`TObject`** member -functions, you can change the behavior of objects in collections: - -- `IsEqual()`is used by the `FindObject() `collection method. By - default, `IsEqual()` compares the two object pointers. - -- `Compare()`returns -1, 0 or 1 depending if the object is smaller, - equal or larger than the other object. By default, a **`TObject`** - has not a valid `Compare()` method. - -- `IsSortable() `returns true if the class is sort able (i.e. if it - has a valid `Compare(`) method). By default, a **`TObject`** is not - sort able. - -- `Hash() `returns a hash value. It needs to be implemented if an - object has to be stored in a collection using a hashing technique, - like **`THashTable`**, **`THashList`** and **`TMap`**. By default, - `Hash(`) returns the address of the object. It is essential to - choose a good hash function. - -The example below shows how to use and override these member functions. - -``` {.cpp} -class TObjNum : public TObject { - private: - Int_t num; // TObjNum is a simple container for an integer. -public: - TObjNum(Int_t i = 0) : num(i) { } - ~TObjNum() { } - void SetNum(Int_t i) { num = i; } - Int_t GetNum() const { return num; } - void Print(Option_t *) const - { printf("num = %dn", num); } - Bool_t IsEqual(TObject *obj) const - { return num == ((TObjNum*)obj)->num; } - Bool_t IsSortable() const { return kTRUE; } - Int_t Compare(const TObject *obj) const - { if (num < ((TObjNum*)obj)->num) return -1; - else if (num > ((TObjNum*)obj)->num) return 1; - else return 0; } - ULong_t Hash() const { return num; } -}; -``` - -## The TIter Generic Iterator - - -As stated above, the **`TIterator`** class is abstract; it is not -possible to create **`TIterator`** objects. However, it should be -possible to write generic code to process all members of a collection so -there is a need for a generic iterator object. A **`TIter`** object acts -as generic iterator. It provides the same `Next()` and `Reset()` methods -as **`TIterator`** although it has no idea how to support them! It works -as follows: - -- To create a **`TIter`** object its constructor must be passed an - object that inherits from **`TCollection`**. The **`TIter`** - constructor calls the `MakeIterator()` method of this collection to - get the appropriate iterator object that inherits from - **`TIterator`**. - -- The `Next()` and `Reset()` methods of **`TIter`** simply call the - `Next()` and `Reset()` methods of the iterator object. - -Therefore, **`TIter`** simply acts as a wrapper for an object of a -concrete class inheriting from **`TIterator`**. - -To see this working in practice, consider the **`TObjArray`** -collection. Its associated iterator is **`TObjArrayIter`**. Suppose -`myarray` is a pointer to a **`TObjArray`** that contains `MyClass` -objects, i.e. - -``` {.cpp} -TObjArray *myarray; -``` - -To create a **`TIter`** object called `myiter`: - -``` {.cpp} -TIter myiter(myarray); -``` - -![](pictures/020001A4.jpg) - -As shown in the diagram, this results in several methods being called: - -- The **`TIter`** constructor is passed a **`TObjArray`** - -- **`TIter`** asks embedded **`TCollection`** to make an iterator - -- **`TCollection`** asks **`TObjArray`** to make an iterator - -- **`TObjArray`** returns a **`TObjArrayIter`**. - -Now define a pointer for `MyClass` objects and set it to each member of -the **`TObjArray`**: - -``` {.cpp} -MyClass *myobject; -while ((myobject = (MyClass *)myiter.Next())) { - // process myobject -} -``` - -The heart of this is the `myiter.Next()` expression which does the -following: - -- The `Next()` method of the **`TIter`** object `myiter` is called - -- The **`TIter`** forwards the call to the **`TIterator`** embedded in - the **`TObjArrayIter`** - -- **`TIterator`** forwards the call to the **`TObjArrayIter`** - -- **`TObjArrayIter`** finds the next `MyClass` object and returns it - -- **`TIter`** passes the `MyClass` object back to the caller - -![](pictures/020001A5.jpg) - -Sometimes the **`TIter`** object is called next, and then instead of -writing: `next.Next() `which is legal, but looks rather odd, iteration -is written as `next()`. This works because the function `operator()` is -defined for the **`TIter`** class to be equivalent to the `Next()` -method. - -## The TList Collection - - -A **`TList`** is a doubly linked list. Before being inserted into the -list the object pointer is wrapped in a **`TObjLink`** object that -contains, besides the object pointer also a previous and next pointer. - -Objects are typically added using: - -- `Add()` - -- `AddFirst(), AddLast()` - -- `AddBefore(), AddAfter()` - -**Main features of`TList`**: very low cost of adding/removing elements -anywhere in the list. - -**Overhead per element**: 1 `TObjLink`, i.e. two 4 (or 8) byte pointers -+ pointer to `vtable` = 12 (or 24) bytes. - -Next figure shows the internal data structure of a **`TList`**. - -![The internal data structure of a TList](pictures/020001A6.jpg) - -### Iterating Over a TList - - -There are four ways to iterate over a **`TList`**: - -- Using the `ForEach` script: - -``` {.cpp} -GetListOfPrimitives()->ForEach(TObject,Draw)(); -``` - -- Using the **`TList`** iterator **`TListIter`** (via the wrapper - class **`TIter`**): - -``` {.cpp} -TIter next(GetListOfTracks()); -while ((TTrack *obj = (TTrack *)next())) - obj->Draw(); -``` - -- Using the **`TObjLink`** list entries (that wrap the - **`TObject`**\*): - -``` {.cpp} -TObjLink *lnk = GetListOfPrimitives()->FirstLink(); -while (lnk) { - lnk->GetObject()->Draw(); - lnk = lnk->Next(); -} -``` - -- Using the **`TList`**'s `After()` and `Before()` member functions: - -``` {.cpp} -TFree *idcur = this; -while (idcur) { - ... - idcur = (TFree*)GetListOfFree()->After(idcur); -} -``` - -Method 1 uses internally method 2. - -Method 2 works for all collection classes. **`TIter`** overloads -`operator()`. - -Methods 3 and 4 are specific for **`TList`**. - -Methods 2, 3 and 4 can also easily iterate backwards using either a -backward **`TIter`** (using argument `kIterBackward`) or by using -`LastLink()` and `lnk>Prev`() or by using the `Before()` method. - -## The TObjArray Collection - - -A **`TObjArray`** is a collection which supports traditional array -semantics via the overloading of `operator[]`. Objects can be directly -accessed via an index. The array expands automatically when objects are -added. At creation time one specifies the default array size (default = -16) and lower bound (default = 0). Resizing involves a re-allocation and -a copy of the old array to the new. This can be costly if done too -often. If possible, set initial size close to expected final size. Index -validity is always checked (if you are 100% sure and maximum performance -is needed you can use `UnCheckedAt()` instead of `At()` or -`operator[]`). If the stored objects are sort able the array can be -sorted using `Sort()`. Once sorted, efficient searching is possible via -the `BinarySearch()` method. The figure shows the internal data -structure of a **`TObjArray`**: - -![The internal data structure of a TObjArray](pictures/020001A7.jpg) - -Iterating can be done using a **`TIter`** iterator or via a simple for -loop: - -``` {.cpp} -for (int i = 0; i <= fArr.GetLast(); i++) -if ((track = (TTrack*)fArr[i])) // or fArr.At(i) - track->Draw(); -``` - -Main features of **`TObjArray`** are simple, well-known array semantics. -**Overhead per element**: none, except possible over sizing of `fCont`. - -## TClonesArray An Array of Identical Objects - - -A **`TClonesArray`** is an array of identical (clone) objects. The -memory for the objects stored in the array is allocated only once in the -lifetime of the clones array. All objects must be of the same class. For -the rest this class has the same properties as a **`TObjArray`**. - -![The internal data structure of a TClonesArray](pictures/020001A8.jpg) - -The figure above shows the internal data structure of a -**`TClonesArray`**. The class is specially designed for repetitive data -analysis tasks, where in a loop many times the same objects, are created -and deleted. The only supported way to add objects to a -**`TClonesArray`** is via the `new` with placement method. The different -`Add()` methods of **`TObjArray`** and its base classes are not -supported. - -### The Idea Behind TClonesArray - - -To reduce the very large number of new and delete calls in large loops -like this (O(100000) x O(10000) times new/delete): - -``` {.cpp} -TObjArray a(10000); -while (TEvent *ev = (TEvent *)next()) { // O(100000) - for (int i = 0; i < ev->Ntracks; i++) { // O(10000) - a[i] = new TTrack(x,y,z,...); - ... - } - ... - a.Delete(); -} -``` - -You better use a **`TClonesArray`** which reduces the number of -new/delete calls to only O(10000): - -``` {.cpp} -TClonesArray a("TTrack", 10000); -while (TEvent *ev = (TEvent *)next()) { // O(100000) - for (int i = 0; i < ev->Ntracks; i++) { // O(10000) - TTrack *track = (Track*)a.ConstructedAt(i); - track->Set(x,y,z,...); - ... - } - ... - a.Clear(); // Or Clear("C") if the track objects must be returned (via Track::Clear) to a default state. -} -``` - -Considering that a pair of new/delete calls on average cost about 70 ms, -O(109) new/deletes will save about 19 hours. For the other collections, -see the class reference guide on the web and the test program -`$ROOTSYS/test/tcollex.cxx.` - -## Template Containers and STL - - -Some people dislike polymorphic containers because they are not truly -"type safe". In the end, the compiler leaves it the user to ensure that -the types are correct. This only leaves the other alternative: creating -a new class each time a new (container organization) / (contained -object) combination is needed. To say the least this could be very -tedious. Most people faced with this choice would, for each type of -container: - -Define the class leaving a dummy name for the contained object type. -When a particular container was needed, copy the code and then do a -global search and replace for the contained class. C++ has a built in -template scheme that effectively does just this. For example: - -``` {.cpp} -template -class ArrayContainer { - private: - T *member[10]; - ... -}; -``` - -This is an array container with a 10-element array of pointers to T, it -could hold up to 10 T objects. This array is flawed because it is static -and hard-coded, it should be dynamic. However, the important point is -that the template statement indicates that T is a template, or -parameterized class. If we need an `ArrayContainer` for Track objects, -it can be created by: - -``` {.cpp} -ArrayContainer MyTrackArrayContainer; -``` - -C++ takes the parameter list and substitutes Track for T throughout the -definition of the class `ArrayContainer`, then compiles the code so -generated, effectively doing the same we could do by hand, but with a -lot less effort. - -This produces code that is type safe, but does have different drawbacks: - -- Templates make code harder to read. - -- At the time of writing this documentation, some compilers can be - very slow when dealing with templates. - -- It does not solve the problem when a container has to hold a - heterogeneous set of objects. - -- The system can end up generating a great deal of code; each - container/object combination has its own code, a phenomenon that is - sometimes referred to as *code bloat*. - -- The Standard Template Library (STL) is part on ANSI C++, and - includes a set of template containers. - diff --git a/documentation/users-guide/ExampleAnalysis.md b/documentation/users-guide/ExampleAnalysis.md deleted file mode 100644 index 3e790f3264586..0000000000000 --- a/documentation/users-guide/ExampleAnalysis.md +++ /dev/null @@ -1,350 +0,0 @@ -# Example Analysis - - -This chapter is an example of a typical physics analysis. Large data -files are chained together and analyzed using the **`TSelector`** class. - -## Explanation - - -This script uses four large data sets from the H1 collaboration at DESY -Hamburg. One can access these data sets (277 Mbytes) from the ROOT web -site at: - -The physics plots generated by this example cannot be produced using -smaller data sets. - -There are several ways to analyze data stored in a ROOT Tree - -- Using `TTree::Draw`: - -- This is very convenient and efficient for small tasks. A - **`TTree`**::Draw call produces one histogram at the time. The - histogram is automatically generated. The selection expression may - be specified in the command line. - -- Using the **`TTreeViewer`**: - -- This is a graphical interface to `TTree::Draw` with the same - functionality. - -- Using the code generated by `TTree::MakeClass`: - -- In this case, the user creates an instance of the analysis class. They - have the control over the event loop and can generate an unlimited - number of histograms. - -- Using the code generated by `TTree::MakeSelector`: Like for the code - generated by **`TTree::MakeClass`**, the user can do complex analysis. - However, they cannot control the event loop. The event loop is - controlled by `TTree::Process` called by the user. This solution is - illustrated by the code below. The advantage of this method is that - it can be run in a parallel environment using PROOF (the Parallel - Root Facility). - -A chain of four files (originally converted from PAW ntuples) is used to -illustrate the various ways to loop on ROOT data sets. Each contains a -ROOT Tree named "`h42`". The class definition in h1analysis.h has been -generated automatically by the ROOT utility **`TTree`**`::MakeSelector` -using one of the files with: - -``` {.cpp} -h42->MakeSelector("h1analysis"); -``` - -This produces two files: h1analysis.h and `h1analysis.C`. A skeleton of -`h1analysis.C` file is made for you to customize. The h1analysis class -is derived from the ROOT class **`TSelector`**. The following members -functions of h1analyhsis (i.e. **`TSelector`**) are called by the -`TTree::Process` method. - -- `Begin`: This function is called every time a loop over the tree - starts. This is a convenient place to create your histograms. - -- `Notify():` This function is called at the first entry of a new tree - in a chain. - -- `ProcessCut`: This function is called at the beginning of each entry - to return a flag true if the entry must be analyzed. - -- `ProcessFill`: This function is called in the entry loop for all - entries accepted by Select. - -- `Terminate`: This function is called at the end of a loop on a - **`TTree`**. This is a convenient place to draw and fit your - histograms. - -To use this program, try the following session. - -First, turn the timer on to show the real and CPU time per command. - -``` {.cpp} -root[] gROOT->Time(); -``` - -*Step A:* create a **`TChain`** with the four H1 data files. The chain -can be created by executed this short script `h1chain.C` below. \$H1 is -a system symbol pointing to the H1 data directory. - -``` {.cpp} -{ - TChain chain("h42"); - chain.Add("$H1/dstarmb.root"); - //21330730 bytes, 21920 events - chain.Add("$H1/dstarp1a.root"); - //71464503 bytes, 73243 events - chain.Add("$H1/dstarp1b.root"); - //83827959 bytes, 85597 events - chain.Add("$H1/dstarp2.root"); - //100675234 bytes, 103053 events -} -``` - -Run the above script from the command line: - -``` {.cpp} -root[] .x h1chain.C -``` - -*Step B*: Now we have a directory containing the four data files. Since -a **`TChain`** is a descendent of `TTree` we can call -**`TChain::Process`** to loop on all events in the chain. The parameter to -the `TChain::Process` method is the name of the file containing the -created **`TSelector`** class (`h1analysis.C`). - -``` {.cpp} -root[] chain.Process("h1analysis.C") -``` - -*Step C*: Same as step B, but in addition fill the event list with -selected entries. The event list is saved to a file "`elist.root`" by -the `TSelector::Terminate` method. To see the list of selected events, -you can do `elist->Print("all")`. The selection function has selected -7525 events out of the 283813 events in the chain of files. (2.65 per -cent) - -``` {.cpp} -root[] chain.Process("h1analysis.C","fillList") -``` - -*Step D:* Process only entries in the event list. The event list is read -from the file in `elist.root` generated by step C. - -``` {.cpp} -root[] chain.Process("h1analysis.C","useList") -``` - -*Step E*: The above steps have been executed with the interpreter. You -can repeat the steps B, C, and D using ACLiC by replacing -"`h1analysis.C`" by "`h1analysis.C+`" or "`h1analysis.C++`". - -*Step F:* If you want to see the differences between the interpreter -speed and ACLiC speed start a new session, create the chain as in step -1, then execute - -``` {.cpp} -root[] chain.Process("h1analysis.C+","useList") -``` - -The commands executed with the four different methods B, C, D and E -produce two canvases shown below: - -![](pictures/030001FD.png) ![](pictures/030001FE.png) - -## Script - - -This is the `h1analsysis.C` file that was generated by -`TTree::MakeSelector` and then modified to perform the analysis. - -``` {.cpp} -#include "h1analysis.h" -#include "TH2.h" -#include "TF1.h" -#include "TStyle.h" -#include "TCanvas.h" -#include "TLine.h" -#include "TEventList.h" - -const Double_t dxbin = (0.17-0.13)/40; // Bin-width -const Double_t sigma = 0.0012; -TEventList *elist = 0; -Bool_t useList, fillList; -TH1F *hdmd; -TH2F *h2; - -//_________________________________________________________ -Double_t fdm5(Double_t *xx, Double_t *par) -{ - Double_t x = xx[0]; - if (x <= 0.13957) return 0; - Double_t xp3 = (x-par[3])*(x-par[3]); - Double_t res = dxbin*(par[0]*TMath::Power(x-0.13957,par[1]) - + par[2]/2.5066/par[4]*TMath::Exp(-xp3/2/par[4]/par[4])); - return res; -} - -//_________________________________________________________ -Double_t fdm2(Double_t *xx, Double_t *par) -{ - Double_t x = xx[0]; - if (x <= 0.13957) return 0; - Double_t xp3 = (x-0.1454)*(x-0.1454); - Double_t res = dxbin*(par[0]*TMath::Power(x-0.13957,0.25) - + par[1]/2.5066/sigma*TMath::Exp(-xp3/2/sigma/sigma)); - return res; -} - -//_________________________________________________________ -void h1analysis::Begin(TTree *tree) -{ -// function called before starting the event loop -// -it performs some cleanup -// -it creates histograms -// -it sets some initialization for the event list - - //initialize the Tree branch addresses - Init(tree); - - //print the option specified in the Process function - TString option = GetOption(); - printf("Starting h1analysis with process option: %sn",option.Data()); - - //Some cleanup in case this function had already been executed - //Delete any previously generated histograms or functions - gDirectory->Delete("hdmd"); - gDirectory->Delete("h2*"); - delete gROOT->GetFunction("f5"); - delete gROOT->GetFunction("f2"); - - //create histograms - hdmd = new TH1F("hdmd","dm_d",40,0.13,0.17); - h2 = new TH2F("h2","ptD0 vs dm_d",30,0.135,0.165,30,-3,6); - - //process cases with event list - fillList = kFALSE; - useList = kFALSE; - fChain->SetEventList(0); - delete gDirectory->GetList()->FindObject("elist"); - - // case when one creates/fills the event list - if (option.Contains("fillList")) { - fillList = kTRUE; - elist = new TEventList("elist","selection from Cut",5000); - } - // case when one uses the event list generated in a previous call - if (option.Contains("useList")) { - useList = kTRUE; - TFile f("elist.root"); - elist = (TEventList*)f.Get("elist"); - if (elist) elist->SetDirectory(0); - //otherwise the file destructor will delete elist - fChain->SetEventList(elist); - } -} -//_________________________________________________________ -Bool_t h1analysis::ProcessCut(Int_t entry) -{ // Selection function to select D* and D0. - - //in case one event list is given in input, - //the selection has already been done. - if (useList) return kTRUE; - // Read only the necessary branches to select entries. - // return as soon as a bad entry is detected - b_md0_d->GetEntry(entry); - if (TMath::Abs(md0_d-1.8646) >= 0.04) return kFALSE; - b_ptds_d->GetEntry(entry); - if (ptds_d <= 2.5) return kFALSE; - b_etads_d->GetEntry(entry); - if (TMath::Abs(etads_d) >= 1.5) return kFALSE; - b_ik->GetEntry(entry); ik--; - //original ik used f77 convention starting at 1 - b_ipi->GetEntry(entry); - ipi--; - b_ntracks->GetEntry(entry); - b_nhitrp->GetEntry(entry); - if (nhitrp[ik]*nhitrp[ipi] <= 1) return kFALSE; - b_rend->GetEntry(entry); - b_rstart->GetEntry(entry); - if (rend[ik]-rstart[ik] <= 22) return kFALSE; - if (rend[ipi]-rstart[ipi] <= 22) return kFALSE; - b_nlhk->GetEntry(entry); - if (nlhk[ik] <= 0.1) return kFALSE; - b_nlhpi->GetEntry(entry); - if (nlhpi[ipi] <= 0.1) return kFALSE; - b_ipis->GetEntry(entry); - ipis--; - if (nlhpi[ipis] <= 0.1) return kFALSE; - b_njets->GetEntry(entry); - if (njets < 1) return kFALSE; - - // if option fillList, fill the event list - if (fillList) elist->Enter(fChain->GetChainEntryNumber(entry)); - - return kTRUE; -} - -//_________________________________________________________ -void h1analysis::ProcessFill(Int_t entry) -{ // Function called for selected entries only - - // read branches not processed in ProcessCut - b_dm_d->GetEntry(entry); - //read branch holding dm_d - b_rpd0_t->GetEntry(entry); - //read branch holding rpd0_t - b_ptd0_d->GetEntry(entry); - //read branch holding ptd0_d //continued... - //fill some histograms - hdmd->Fill(dm_d); - h2->Fill(dm_d,rpd0_t/0.029979*1.8646/ptd0_d); -} - -//_________________________________________________________ -void h1analysis::Terminate() -{ // Function called at the end of the event loop - - //create the canvas for the h1analysis fit - gStyle->SetOptFit(); - TCanvas *c1 = new TCanvas("c1","h1analysis analysis",10,10,800,600); - c1->SetBottomMargin(0.15); - hdmd->GetXaxis()->SetTitle("m_{K#pi#pi}-m_{K#pi}[GeV/c^{2}]"); - hdmd->GetXaxis()->SetTitleOffset(1.4); - - //fit histogram hdmd with function f5 using - //the loglikelihood option - TF1 *f5 = new TF1("f5",fdm5,0.139,0.17,5); - f5->SetParameters(1000000,.25,2000,.1454,.001); - hdmd->Fit("f5","lr"); - - //create the canvas for tau d0 - gStyle->SetOptFit(0); - gStyle->SetOptStat(1100); - TCanvas *c2 = new TCanvas("c2","tauD0",100,100,800,600); - c2->SetGrid(); - c2->SetBottomMargin(0.15); - - // Project slices of 2-d histogram h2 along X , - // then fit each slice with function f2 and make a - // histogram for each fit parameter. - // Note that the generated histograms are added - // to the list of objects in the current directory. - - TF1 *f2 = new TF1("f2",fdm2,0.139,0.17,2); - f2->SetParameters(10000,10); - h2->FitSlicesX(f2,0,0,1,"qln"); - TH1D *h2_1 = (TH1D*)gDirectory->Get("h2_1"); - h2_1->GetXaxis()->SetTitle("#tau[ps]"); - h2_1->SetMarkerStyle(21); - h2_1->Draw(); - c2->Update(); - TLine *line = new TLine(0,0,0,c2->GetUymax()); - line->Draw(); - - // save the event list to a Root file if one was produced - if (fillList) { - TFile efile("elist.root","recreate"); - elist->Write(); - } -} -``` diff --git a/documentation/users-guide/FittingHistograms.md b/documentation/users-guide/FittingHistograms.md deleted file mode 100644 index 734a35112612d..0000000000000 --- a/documentation/users-guide/FittingHistograms.md +++ /dev/null @@ -1,1918 +0,0 @@ -# Fitting Histograms - - -To fit a histogram you can use the Fit Panel on a visible histogram -via the context menu, or you can use the `TH1::Fit` method. The -Fit Panel, which is limited, is best for prototyping. The histogram -needs to be drawn in a pad before the Fit Panel is invoked. The method -`TH1::Fit` is more powerful and is used in scripts and programs. - -## The Fit Method - -The Fit method is implemented in ROOT for the histogram classes **`TH1`**, -the sparse histogram classes, `THnSparse`, the graph classes, `TGraph`, -`TGraph2D` and `TMultiGraph` for fitting a collection of Graphs with the same function. - -### The TH1::Fit Method - -To fit a histogram programmatically, you can use the `TH1::Fit` -method. Here is the signatures of `TH1::Fit` and an explanation of the -parameters: - -``` {.cpp} - TFitResultPtr Fit(TF1 *function, Option_t *option, Option_t *goption, - Axis_t xxmin, Axis_t xxmax) -``` -- `function` a pointer to the fitted function (the fit model) object. - One can also use the function name. This name may be one of ROOT pre-defined - function names or a user-defined function. See the next paragraph for the list of pre-defined functions. - -- `*option:` The second parameter is the fitting option. Here is the - list of fitting options: - - - "`W`" Set all weights to 1 for non empty bins; ignore error bars - - - "`WW`" Set all weights to 1 including empty bins; ignore error - bars - - - "`I`" Use integral of function in bin instead of value at bin - center - - - "`L`" Use log likelihood method (default is chi-square method). To be used when -the histogram represents counts - - - "`WL`" Weighted log likelihood method. To be used when the histogram has been filled with - weights different than 1. - - - "`P`" Use Pearson chi-square method, using expected errors instead of the observed one given by `TH1::GetBinError` (default case). - The expected error is instead estimated from the square-root of the bin function value. - - - "`Q`" Quiet mode (minimum printing) - - - "`V`" Verbose mode (default is between Q and V) - - - "`S`" The result of the fit is returned in the `TFitResultPtr`. - - - "`E`" Perform better errors estimation using the Minos technique - - - "`M`" Improve fit results, by using the *IMPROVE* algorithm of TMinuit. - - - "`R`" Use the range specified in the function range - - - "`N`" Do not store the graphics function, do not draw - - - "`0`" Do not plot the result of the fit. By default the fitted - function is drawn unless the option "`N`" above is specified. - - - "`+`" Add this new fitted function to the list of fitted functions - (by default, the previous function is deleted and only the last - one is kept) - - - "`B`"Use this option when you want to fix one or more parameters -and the fitting function is a predefined one, like `polN`, `expo`, `landau`, `gaus`. -Note that in case of pre-defined functions some default initial values and limits are set. - - - - "`C`"In case of linear fitting, don't calculate the chisquare - (saves time). - - - "`F`"If fitting a linear function (e.g. `polN`), switch to use the default minimizer (e.g. `Minuit`). By default, - `polN` functions are fitted by the linear fitter. - -- `*goption: `The third parameter is the graphics option that is the - same as in the `TH1::Draw` (see the chapter Draw Options). - -- `xxmin`, `xxmax:`Thee fourth and fifth parameters specify the - range over which to apply the fit. - -By default, the fitted function object is added to the histogram and -is drawn in the current pad. - - -### The TGraph::Fit Method - -The signature for fitting a TGraph is exactly the same as for the **`TH1`**. Only some options apply only for fitting histograms, -these are the options "`L`", "`WL`" and "`I`". -These options apply instead only for `TGraph::Fit`, the rest of options (appart from "`L`", "`WL`" and "`I`" are the same) - -* `TGraph` specific *options* - - - "`EX0`" When fitting a `TGraphErrors` or a `TgraphAsymErrors` the errors on the coordinates are not used in the fit - - - "`ROB`" in case of linear fitting use the Robust fitting. Compute the LTS regression coefficients (robust (resistant) regression), - using the default fraction of good points. - - "`ROB=0.x`" as above, but compute the LTS regression coefficients, using 0.x as a fraction of good points. - -## The `TF1` function class - -Here we will show how to create the **`TF1`** class that is used for fitting histograms and graphs. - -### Fit with a Predefined Function - - -To fit a histogram with a predefined function, simply pass the name of -the function in the first parameter of `TH1::Fit`. For example, -this line fits histogram object `hist` with a Gaussian. - -``` {.cpp} -root[] hist.Fit("gaus"); -``` - -The initial parameter values (and eventual limits) for pre-defined functions are set -automatically. For overriding the default limits values use the fit option `B`. - -The list of pre-defined functions that can be used with the `Fit` method is the following: - -- "`gaus`" Gaussian function with 3 parameters: - `f(x) = p0*exp(-0.5*((x-p1)/p2)^2)` - -- "`expo`"An Exponential with 2 parameters: `f(x) = exp(p0+p1*x)` - -- "`pol`*`N`*" A polynomial of degree *N*, where N is a number between 0 and 9: - `f(x) = p0 + p1*x + p2*x2 +...` - -- "`chebyshev`*`N`*" A Chebyshev polynomial of degree *N*, where N is a number between 0 and 9: - `f(x) = p0 + p1*x + p2*(2*x2-1) +...` - -- "`landau`" Landau function with mean and sigma. This function has -been adapted from the `CERNLIB` routine `G110 denlan` (see `TMath::Landau`). - -- "`gausn`" Normalized form of the gaussian function with 3 parameters -`f(x) = p0*exp(-0.5*((x-p1)/p2)^2)/(p2 *sqrt(2PI))` - - -### Creating User-Defined Functions (TF1) - - -You can create a **`TF1`** object and use it in the call the -`TH1::Fit`. The parameter in to the `Fit` method is the NAME of -the **`TF1`** object. There are three ways to create a **`TF1`**. - -- Using C++ expression using x with a fixed set of operators and - functions defined in **`TFormula`**. - -- Same as first one, with parameters - -- Using a function that you have defined. This can be a free function or - a functor object or a particular member function of a class. - -#### Creating a TF1 with a Formula - - -Let's look at the first case. Here we call the **`TF1`** constructor -by giving it the formula: `sin(x)/x`. - -``` {.cpp} -root[] TF1 *f1 = new TF1("f1","sin(x)/x",0,10) -``` - -You can also use a **`TF1`** object in the constructor of another -**`TF1`**. - -``` {.cpp} -root[] TF1 *f2 = new TF1("f2","f1*2",0,10) -``` - -#### Creating a TF1 with Parameters - - -The second way to construct a **`TF1`** is to add parameters to the -expression. Here we use two parameters: - -``` {.cpp} -root[] TF1 *f1 = new TF1("f1","[0]*x*sin([1]*x)",-3,3); -``` - -![The function `x*sin(x)`](pictures/03000060.png) - -The parameter index is enclosed in square brackets. To set the initial -parameters explicitly you can use: - -``` {.cpp} -root[] f1->SetParameter(0,10); -``` - -This sets parameter 0 to 10. You can also use `SetParameters` to set -multiple parameters at once. - -``` {.cpp} -root[] f1->SetParameters(10,5); -``` - -This sets parameter 0 to 10 and parameter 1 to 5. We can now draw the -**`TF1`**: - -``` {.cpp} -root[] f1->Draw() -``` - -#### Creating a TF1 with a User Function - - -The third way to build a **`TF1`** is to define a function yourself -and then pass the function pointer to the constructor. A function for a **`TF1`** -constructor needs to have this exact signature: - -``` {.cpp} -Double_t fitf(Double_t *x,Double_t *par) -``` - -The two parameters are: - -- `x ` a pointer to the dimension array. Each element contains a - dimension. For a 1D histogram only `x[0]` is used, for a 2D - histogram `x[0]` and `x[1]` is used, and for a 3D histogram - `x[0]`, `x[1]`, and `x[2]` are used. For histograms, only 3 - dimensions apply, but this method is also used to fit other - objects, for example an ntuple could have 10 dimensions. - -- `par` a pointer to the parameters array. This array contains the - current values of parameters when it is called by the fitting - function. - -The following script `$ROOTSYS/tutorials/fit/myfit.C` illustrates how -to fit a 1D histogram with a user-defined function. First we declare -the function. - -``` {.cpp} - // define a function with 3 parameters - Double_t fitf(Double_t *x,Double_t *par) { - Double_t arg = 0; - if (par[2]!=0) arg = (x[0] - par[1])/par[2]; - Double_t fitval = par[0]*TMath::Exp(-0.5*arg*arg); - return fitval; - } -``` - -Now we use the function: - -``` {.cpp} - // this function uses fitf to fit a histogram - void fitexample() { - - // open a file and get a histogram - TFile *f = new TFile("hsimple.root"); - TH1F *hpx = (TH1F*)f->Get("hpx"); - - // Create a TF1 object using the function defined above. - // The last three parameters specify the number of parameters - // for the function. - TF1 *func = new TF1("fit",fitf,-3,3,3); - // set the parameters to the mean and RMS of the histogram - func->SetParameters(500,hpx->GetMean(),hpx->GetRMS()); - - // give the parameters meaningful names - func->SetParNames ("Constant","Mean_value","Sigma"); - - // call TH1::Fit with the name of the TF1 object - hpx->Fit("fit"); - } -``` - - -You can create a **`TF1`** also from a C++ function object (functor) with parameters -A **`TF1`** can be created from any C++ class implementing this member function: - -```{.cpp} -double operator()(double *x, double *p) -``` -The advantage of the function object is that it can have a state and reference therefore what-ever other object -the user needs, without using globals. This is an example to define first the function object - -``` {.cpp} -class MyFunctionObject { - public: - // use constructor to customize your function object - MyFunctionObject(......) { ......} - - double operator() (double *x, double *p) { - // function implementation using class data members - } -}; -``` - -and then use it to create the **`TF1`**: - -```{.cpp} - MyFunctionObject fobj(....); // create the function object - TF1 * f = new TF1("f",fobj,xmin,xmax,npar); // create TF1 class with n-parameters and range [xmin,xmax] -``` - -If using C++11, one can create a **`TF1`** also from a C++ `lambda` function: - -```{.cpp} -// create TF1 class with 2 parameters and range [xmin,xmax] using a lambda -TF1 * f = new TF1("f",[](double*x,double*p){return p[0] + p[1]*x[0];},xmin,xmax,2); -``` - -## Configuring the Fit - -We will show here some configuration actions that can or must be done -when fitting histogram or graph using the `Fit` method. - -### Fixing and Setting Parameters' Bounds - -Parameters must be initialized before invoking the `Fit` method. The -setting of the parameter initial values is automatic for the -predefined functions: `poln`, `exp`, `gaus`, and `landau`. You can fix -one or more parameters by specifying the "B" option when calling the -`Fit` method. When a function is not predefined, the fit parameters -must be initialized to some value as close as possible to the expected -values before calling the fit function. - -To set bounds for one parameter, use `TF1::SetParLimits`: - -``` {.cpp} - func->SetParLimits(0,-1,1); -``` - -When the lower and upper limits are equal, the parameter is fixed. -Next two statements fix parameter 4 at 10. - -``` {.cpp} - func->SetParameter(4,10); - func->SetParLimits(4,10,10); -``` - -However, to fix a parameter to 0, one must call the `FixParameter` -function: - -``` {.cpp} - func->SetParameter(4,0); - func->FixParameter(4,0); -``` - -Note that you are not forced to set the limits for all parameters. For -example, if you fit a function with 6 parameters, you can: - -``` {.cpp} - func->SetParameters(0,3.1,1.e-6,-1.5,0,100); - func->SetParLimits(3,-10,4); - func->FixParameter(4,0); -``` - -With this setup, parameters 0`->`2 can vary freely, parameter 3 has -boundaries [-10, 4] with initial value -1.5, and parameter 4 is fixed -to 0. - -### Fitting Sub Ranges - -By default, `TH1::Fit` will fit the function on the defined histogram -range. You can specify the option "`R`" in the second parameter of -`TH1::Fit` to restrict the fit to the range specified in the **`TF1`** -constructor. In this example, the fit will be limited to -3 to 3, the -range specified in the **`TF1`** constructor. - -``` {.cpp} -root[] TF1 *f1 = new TF1("f1","[0]*x*sin([1]*x)",-3,3); -root[] hist->Fit("f1","R"); -``` - -You can also specify a range in the call to `TH1::Fit`: - -``` {.cpp} -root[] hist->Fit("f1","","",-2,2) -``` - -See macros `$ROOTSYS/tutorials/fit/myfit.C` and `multifit.C` as more -completed examples. - - -### Fitting Multiple Sub Ranges - - -The script for this example is `$ROOTSYS/tutorials/fit/multifit.C`. It -shows how to use several Gaussian functions with different parameters -on separate sub ranges of the same histogram. To use a Gaussian, or -any other ROOT built in function, on a sub range you need to define a -new **`TF1`**. Each is 'derived' from the canned function `gaus`. - -![Fitting a histogram with several Gaussian -functions](pictures/03000062.png) - -First, four **`TF1`** objects are created - one for each sub-range: - -``` {.cpp} - g1 = new TF1("m1","gaus",85,95); - g2 = new TF1("m2","gaus",98,108); - g3 = new TF1("m3","gaus",110,121); - // The total is the sum of the three, each has 3 parameters - total = new TF1("mstotal","gaus(0)+gaus(3)+gaus(6)",85,125); -``` - -Next, we fill a histogram with bins defined in the array x. - -``` {.cpp} - // Create a histogram and set it's contents - h = new TH1F("g1","Example of several fits in subranges", - np,85,134); - h->SetMaximum(7); - for (int i=0; iSetBinContent(i+1,x[i]); - } - // Define the parameter array for the total function - Double_t par[9]; -``` - -When fitting simple functions, such as a Gaussian, the initial values -of the parameters are automatically computed by ROOT. In the more -complicated case of the sum of 3 Gaussian functions, the initial -values of parameters must be set. In this particular case, the initial -values are taken from the result of the individual fits. The use of -the "+" sign is explained below: - -``` {.cpp} - // Fit each function and add it to the list of functions - h->Fit(g1,"R"); - h->Fit(g2,"R+"); - h->Fit(g3,"R+"); - - // Get the parameters from the fit - g1->GetParameters(&par[0]); - g2->GetParameters(&par[3]); - g3->GetParameters(&par[6]); - - // Use the parameters on the sum - total->SetParameters(par); - h->Fit(total,"R+"); -``` - -### Adding Functions to the List - - -The example `$ROOTSYS/tutorials/fit/multifit.C` also illustrates how -to fit several functions on the same histogram. By default a Fit -command deletes the previously fitted function in the histogram -object. You can specify the option "+" in the second parameter to add -the newly fitted function to the existing list of functions for the -histogram. - -``` {.cpp} -root[] hist->Fit("f1","+","",-2,2) -``` - -Note that the fitted function(s) are saved with the histogram when it -is written to a ROOT file. - - -## Example of fit: Combining Functions - -You can combine functions to fit a histogram with their sum as it is -illustrated in the macro `FitDemo.C` -(`$ROOTSYS/tutorials/fit/FittingDemo.C)`. We have a function that is -the combination of a background and Lorentzian peak. Each function -contributes 3 parameters: - -$$ -y(E) = a_{1} + a_{2}E + a_{3}E^{2} + \frac{A_{p}(\frac{G}{2p})} -{(E-m)^{2} + (\frac{G}{2})^2 } -$$ - - - -BackgroundLorentzian Peak - -`par[0]` = $a_{1}$ `par[0]` = $A_{p}$ - -`par[1]` = $a_{2}$ `par[1]` = $G$ - -`par[2]` = $a_{3}$ `par[2]` = $m$ - -The combination function (`fitFunction`) has six parameters: - -`fitFunction = background(x,par) + LorentzianPeak(x,&par[3])` - -`par[0]=`$a_{1}$ `par[1]=`$a_{2}$ `par[2]=`$a_{3}$ `par[3]=`$A_{p}$ -`par[4]=`$G$ `par[5]=`$m$ - -This script creates a histogram and fits it with the combination of two -functions. First we define the two functions and the combination -function: - -``` {.cpp} - // Quadratic background function - Double_t background(Double_t *x, Double_t *par) { - return par[0] + par[1]*x[0] + par[2]*x[0]*x[0]; - } - - // Lorentzian Peak function - Double_t lorentzianPeak(Double_t *x, Double_t *par) { - return (0.5*par[0]*par[1]/TMath::Pi()) / TMath::Max(1.e-10, - (x[0]-par[2])*(x[0]-par[2])+ .25*par[1]*par[1]); - } - - // Sum of background and peak function - Double_t fitFunction(Double_t *x, Double_t *par) { - return background(x,par) + lorentzianPeak(x,&par[3]); - } - - void FittingDemo() { - // bevington exercise by P. Malzacher, modified by R. Brun - const int nBins = 60; - Stat_t data[nBins] = { 6, 1,10,12, 6,13,23,22,15,21, - 23,26,36,25,27,35,40,44,66,81, - 75,57,48,45,46,41,35,36,53,32, - 40,37,38,31,36,44,42,37,32,32, - 43,44,35,33,33,39,29,41,32,44, - 26,39,29,35,32,21,21,15,25,15}; - TH1F *histo = new TH1F("example_9_1", - "Lorentzian Peak on Quadratic Background",60,0,3); - - for(int i=0; i < nBins; i++) { - // we use these methods to explicitly set the content - // and error instead of using the fill method. - histo->SetBinContent(i+1,data[i]); - histo->SetBinError(i+1,TMath::Sqrt(data[i])); - } - // create a TF1 with the range from 0 to 3 and 6 parameters - TF1 *fitFcn = new TF1("fitFcn",fitFunction,0,3,6); - - // first try without starting values for the parameters - // this defaults to 1 for each param. - histo->Fit("fitFcn"); - // this results in an ok fit for the polynomial function however - // the non-linear part (Lorentzian -``` - -![The output of the FittingDemo() example](pictures/03000070.png) - -## Result of the fit - -Here we will show how to obtain the result of the fit (fitted function, parameter values, errors -and eventually the covariance and correlation matrix). - -### Associated Function - - -One or more objects (typically a **`TF1\*`**) can be added to the list -of functions (`fFunctions`) associated to each histogram. A call to -`TH1::Fit` adds the fitted function to this list. Given a histogram -`h`, one can retrieve the associated function with: - -``` {.cpp} - TF1 *myfunc = h->GetFunction("myfunc"); -``` - -### Access to the Fit Parameters and Results - - -If the histogram (or graph) is made persistent, the list of associated -functions is also persistent. Retrieve a pointer to the function with -the `TH1::GetFunction()` method. Then you can retrieve the fit -parameters from the function (**`TF1`**) with calls such as: - -``` {.cpp} -root[] TF1 *fit = hist->GetFunction(function_name); -root[] Double_t chi2 = fit->GetChisquare(); -// value of the first parameter -root[] Double_t p1 = fit->GetParameter(0); -// error of the first parameter -root[] Double_t e1 = fit->GetParError(0); -``` - -Using the fit option `S` one can access the full result of the fit including the covariance and correlation matrix. -See later the paragraph `TFitResult`. - -### Associated Errors - - -By default, for each bin, the sum of weights is computed at fill time. -One can also call `TH1::Sumw2` to force the storage and computation of -the sum of the square of weights per bin. If Sumw2 has been called, -the error per bin is computed as the `sqrt(sum of squares of -weights)`; otherwise, the error is set equal to the -`sqrt(bin content)`. To return the error for a given bin number, do: - -``` {.cpp} - Double_t error = h->GetBinError(bin); -``` - -Empty bins are excluded in the fit when using the Chi-square fit method. -When fitting an histogram representing counts (i.e with Poisson statistics) it is recommended to -use the Log-Likelihood method (option ‘`L`' or "`WL`"), particularly in case of low statistics. -When the histogram has been filled with weights different than one, a weighted likelihood method can be used -and the errors retrieved from the fit are corrected following a procedure described in paragraph 8.5.2 of the book, -*F. James, Statistical Methods in Experimental Physics, 2nd Edition*. - -### Fit Statistics - - -You can change the statistics box to display the fit parameters with the -`TStyle::SetOptFit(mode)` method. This parameter has four digits: -`mode = pcev` (`default = 0111`) - -- `p` = 1 print probability -- `c` = 1 print Chi-square/number of degrees of freedom -- `e` = 1 print errors (if `e=1`, `v` must be 1) -- `v` = 1 print name/values of parameters - -For example, to print the fit probability, parameter names/values, and -errors, use: - -``` {.cpp} - gStyle->SetOptFit(1011); -``` - -## The Fit Panel - - -![The Fit Panel](pictures/03000061.png) - -To display the Fit Panel right click on a histogram to pop up the -context menu, and then select the menu entry Fit Panel. - -The new Fit Panel GUI is available in ROOT v5.14. Its goal is to -replace the old Fit Panel and to provide more user friendly way for -performing, exploring and comparing fits. - -By design, this user interface is planned to contain two tabs: -"General" and "Minimization". Currently, the "General" tab provides -user interface elements for setting the fit function, fit method and -different fit, draw, print options. -The "Minimization tab" provides the option to set the Minimizer to use in the fit and -its specific options. - -The new fit panel is a modeless dialog, i.e. when opened, it does not -prevent users from interacting with other windows. Its first prototype -is a singleton application. When the Fit Panel is activated, users can -select an object for fitting in the usual way, i.e. by left-mouse -click on it. If the selected object is suitable for fitting, the fit -panel is connected with this object and users can perform fits by -setting different parameters and options. - -### Function Choice and Settings - - -*‘Predefined' combo box* - contains a list of predefined functions in -ROOT. You have a choice of several polynomials, a Gaussian, a Landau, -and an Exponential function. The default one is Gaussian. - -*‘Operation' radio button group* defines the selected operational mode -between functions: - -*Nop* - no operation (default); - -*Add* - addition; - -*Conv* - convolution (will be implemented in the future). - -Users can enter the function expression into the text entry field -below the ‘Predefined' combo box. The entered string is checked after -the Enter key was pressed and an error message shows up, if the -function string is not accepted. - -‘*Set Parameters*' button opens a dialog for parameters settings, -which will be explained later. - -### Fitter Settings - - -*‘Method' combo box* currently provides only two fit model choices: -Chi-square and Binned Likelihood. The default one is Chi-square. The -Binned Likelihood is recommended for bins with low statistics. - -*‘Linear Fit' check button* sets the use of Linear fitter when is -selected. Otherwise the minimization is done by Minuit, i.e. fit -option "`F`" is applied. The Linear fitter can be selected only for -functions linear in parameters (for example - `polN)`. - -*‘Robust' number entry* sets the robust value when fitting graphs. - -*‘No Chi-square' check button* switch On/Off the fit option "`C`" - -do not calculate Chi-square (for Linear fitter). - -*‘Integral' check button* switch On/Off the option "`I`" - use -integral of function instead of value in bin center. - -*‘Best Errors'* sets On/Off the option "`E`" - better errors -estimation by using Minos technique. - -*‘All weights = 1'* sets On/Off the option "`W`"- all weights set to 1 -excluding empty bins; error bars ignored. - -*‘Empty bins, weights=1'* sets On/Off the option "`WW`" - all weights -equal to 1 including empty bins; error bars ignored. - -*‘Use range'* sets On/Off the option "`R`" - fit only data within the -specified function range. Sliders settings are used if this option is -set to On. Users can change the function range values by pressing the -left mouse button near to the left/right slider edges. It is possible -to change both values simultaneously by pressing the left mouse button -near to the slider center and moving it to a new position. - -*‘Improve fit results'* sets On/Off the option "`M`"- after minimum is -found, search for a new one. - -*‘Add to list'* sets On/Off the option "`+`"- add function to the list -without deleting the previous one. When fitting a histogram, the -function is attached to the histogram's list of functions. By default, -the previously fitted function is deleted and replaced with the most -recent one, so the list only contains one function. Setting this -option to On will add the newly fitted function to the existing list -of functions for the histogram. Note that the fitted functions are -saved with the histogram when it is written to a ROOT file. By -default, the function is drawn on the pad displaying the histogram. - -### Draw Options - - -*‘SAME'* sets On/Off function drawing on the same pad. When a fit is -executed, the image of the function is drawn on the current pad. - -*‘No drawing'* sets On/Off the option "`0`"- do not draw the fit -results. - -*‘Do not store/draw'* sets On/Off option "`N`"- do not store the -function and do not draw it. - -### Advances Options - -The advance option button is enabled only after having performed the fit and provides -additional drawing options that can be used after having done the fit. These new drawing tools, -which can be selected by the "Advanced Drawing Tool" panel that pops up when clicking the "Advanced" button, are: - -* *Contour*: to plot the confidence contour of two chosen parameters. One can select the number of points to draw the contour -(more points might require more time to compute it), the parameters and the desired confidence level . - -* *Scan* : to plot a scan of the minimization function (likelihood or chi-squared) around the minimum as function of the chosen parameter. - -* *Conf Interval* : to plot the confidence interval of the fitted function as a filled coloured band around its central value. - One can select the desired confidence level for the band to be plotted. - -### Print Options - - -This set of options specifies the amount of feedback printed on the -root command line after performed fits. - -*‘Verbose'* - prints fit results after each iteration. - -*‘Quiet'* - no fit information is printed. - -*‘Default'* - between Verbose and Quiet. - -### Command Buttons - - -*Fit button* - performs a fit taking different option settings via the -Fit Panel interface. - -*Reset* - sets the GUI elements and related fit settings to the -default ones. - -*Close* - closes the Fit panel window. - -### Minimization Options - -With this tab one can select specific options for minimization. These include - -* The minimizer library ( *Minuit*, *Minuit2*, *Fumili*, *GSL*, *Genetics* ) -* The method (algorithm) for minimization. For example for Minuit one can choose between (*Migrad*, *Simplex* or *Scan*) -* Error definition -* Minimization tolerance -* Number of iterations/function calls -* Print Level: (*Default*, *Verbose* or *Quiet*). - - - -## New ROOT::Fit classes - -The fitting of the data objects in ROOT, histograms, graphs and tree is performed via some common classes, -which are defined in the `ROOT::Fit` namespace. -These classes can be classified in the following groups: - -* User classes driving the fit: `ROOT::Fit::Fitter` for executing the fit, `ROOT::Fit::FitConfig` for configuring the fit, - `ROOT::Fit::ParameterSettings` to define the properties of the fit parameters (initial - values, bounds, etc..), `ROOT::Fit::FitResult` for storing the result of the fit. -* Data classes containing the data sets used in the fitting. These classes are the`ROOT::Fit::BinData`for describing bin data sets, - thus data points containing both coordinates and a corresponding value/weight - with optionally an error on the value or the coordinate and the `ROOT::Fit::UnBinData` for un-binned data sets, - which consists only of a vector of coordinate values. The coordinate values can be - one-dimensional (i.e. one entry per event) or multi-dimensional (N entries per event). -* Function classes defining the type of fit (the objective function used for fitting): - - `ROOT::Fit::Chi2FCN` for chi2 (least-square fits), - - `ROOT::Fit::PoissonLikelihoodFCN` for binned likelihood fits of histograms, - - `ROOT::Fit::LogLikelihoodFCN` for generic un-binned likelihood fits. - These classes are templated on the type of function interface they implement (see later). User convenient typedefs are also provided. - They derive from the common generic interface multi-dimensional for function evaluation, `ROOT::Math::IBaseFunctionMultiDim`. - -In addition the fitter classes make uses of the generic interfaces for parametric function evaluations, `ROOT::Math::IParametricFunctionMultiDim` -to define the fit model function and use the `ROOT::Math::Minimizer` interface to perform the minimization of the objective function. -More information about the function interface and the multi-dimensional minimization in ROOT is given in the Mathematical Library chapter. - -Here we present a detailed description of the `ROOT::Fit` classes and how to use them. -Using these classes instead of the interface provided directly in the ROOT data objects, like `TH1::Fit` allow are more fine control -to configure and customise the fits. For example, using these classes a combined fit of several histograms can be performed. - -To understand how these class work, let's go through a simple example, such as fitting an histogram. - -When fitting an histogram, instead of using `TH1::Fit` we will show in the following hot wo use the `ROOT::Fit` classes. -We will show how to perform the following different type of fits with the histogram data: -* a least square fit using the observed errors (Neyman chi-squared); -* a least square fit using the expected errors from the function (Pearson chi-squared); -* a binned likelihood fit; -* an extended unbinned likelihood fits, if the histogram has been set to store in the buffer the original data used to fill it. - - -Let's go through all the steps required for performing these fits using the `ROOT::Fit::Fitter` class. -These steps are: -1. Create the input fit data object. -2. Create the input model function. -3. Configure the fit. -4. Perform the data fitting. -5. Examine the result. - -### Creating the input fit data - -We have two types of input data, binned data (class `ROOT::Fit::BinData`) used for least square (chi-square) fits of histograms or `TGraph` objects -or un-binned data (class `ROOT::Fit::UnBinData`) used for -fitting vectors of data points (e.g. from a `TTree`). - -#### Using Binned data - -Let's suppose we have an histogram, represented as a **`TH1`** type object (it can be one or multi-dimensional). The following shows how to create and -fill a `ROOT:Fit::BinData` object. - -``` {.cpp} - ROOT::Fit::DataOptions opt; - opt.fIntegral = true; - ROOT::Fit::BinData data(opt); - // fill the bin data using the histogram - // we can do this using the following helper function from the Hist library - TH1 * h1 = (TH1*) gDirectory->Get("myHistogram"); - ROOT::Fit::FillData(data, h1); -``` - -In this code example, we have used the utility function of the *Hist* library, `ROOT::Fit::FillData` to fill the `BinData` object. -The `ROOT::Fit::FillData` is defined in the headerfile `HFitInterface.h` and it has a signature for all different ROOT objects, -like `TH1`, `THnBase`, `TGraph`, `TGraph2D` and `TMultiGraph` -It is possible to specify, when creating the `BinData` object, the data range we want to use and some fitting options we want to apply -to fill in the object and later when fitting. -The fit data options are controlled by the ``ROOT::Fit::DataOptions`` class, the range by the ``ROOT::Fit::DataRange`` class. - -Here is an example how to specify the input option to use the integral of the function value in the bin instead of using the function value -evaluated at the bin center, when doing the fit and to use a -range beween the 'xmin' and 'xmax' values. - -``` {.cpp} - ROOT::Fit::DataOptions opt; - opt.fIntegral = true; - ROOT::Fit::DataRange range(xmin,xmax); - ROOT::Fit::BinData data(opt,range); - // fill the bin data using the histogram - // we can do this using the following helper function from the Hist library - TH1 * h1 = (TH1*) gDirectory->Get("myHistogram"); - ROOT::Fit::FillData(data, h1); -``` - -The list of possible fit options available is the following: -``` {.cpp} - ROOT::Fit::DataOptions opt; - opt.fIntegral = true; // use integral of bin content instead of bin center (default is false). - opt.fBinVolume = true; // normalize data by the bin volume (default is false). - // This is for fitting density functions in histograms with variable bin sizes. - opt.fUseRange =true; // use the function range when creating the fit data (default is false). - opt.fExpErrors = true; // use the expected errors estimated from the function values - // assuming Poisson statistics and not the observed errors (default is false). - opt.fUseEmpty = true; // use empty bins when fitting (default is false). If fExpErrors - // is not set an arbitrary error = 1 is assigned to those bins. - opt.fErrors1 = true; // Set all measured errors to 1 (default is false). - opt.fCoordErrors = false; // When available coordinate errors are not used in the fit - // (default is true: the errors are used when they are available, - // e.g. fitting a TGraphErrors). - opt.fAsymErrors = false; // When available asymmetric errors are considered in the fit - // (default is true, the asymmetric errors are used when they are available, - // e.g. fitting a TGraphAsymmErrors). -``` - -The `ROOT::Fit::DataRange` class supports defining multiple rectangular ranges in each dimension, and supports n-dimension. -The function `DataRange::AddRange(icoord,xmin,xmax)` adds a range in -the coordinate `icoord` with lower value `xmin` and upper value `xmax`: - - -``` {.cpp} - ROOT::Fit::DataRange range; - range.AddRange(icoordinate, xmin, xmax); -``` - -#### Using Un-Binned data - -The unbinned data sets are represented with the `ROOT::Fit::UnBinData` class. -For creating un-binned data sets, a `ROOT::Fit::UnBinData` object, one has two possibilities: -1. Copy the data inside `ROOT::Fit::UnBinData`. One can create an empty `UnBinData` object, iterate on the data and add the data point one by one, or directly create the `UnBinData` - object from a data iterator. In this case an input `ROOT::Fit::DataRange` object is passed in order to copy the data according to the given range. - 2. Use `ROOT::Fit::UnBinData` as a wrapper to an external data storage. In this case the `UnBinData` object is created from an iterator or pointers to the data and the data are not copied - inside. In this case the data cannot be selected according to a specified range. All the data points will be included in the fit. - -The `ROOT::Fit::UnBinData` class supports also weighted data. In addition to the data points (coordinates), which can be of arbitrary `k` dimensions, the class can be constructed from a vector of -weights. This is an example of taking data from an histogram buffer of a **`TH1`** object: - -``` {.cpp} - double * buffer = histogram->GetBuffer(); - // number of entry is first entry in the buffer - int n = buffer[0]; - // when creating the data object it is important to create with the size of the data - ROOT::Fit::UnBinData data(n); - for (int i = 0; i < n; ++i) - data.add(buffer[2*i+1]); // the buffer of 1D histogram contains nevt,x1,w1,x2,w2,...... -``` - -Instead in this example we will create a 2-dim `UnBinData` object with the contents from a ROOT `TTree` - -``` {.cpp} - TFile * file = TFile::Open("hsimple.root"); - TTree *ntuple = 0; file->GetObject("ntuple",ntuple); - // select from the tree the data we want to use for fitting - // we use TTree::Draw for this - int nevt = ntuple->Draw("px:py","","goff"); - double * x = ntuple->GetV1(); - double * y = ntuple->GetV2(); - ROOT::Fit::UnBinData data(nevt, x, y ); -``` - -### Creating the Fit model - -In order to fit a data sets we need a model to describe our data, e.g. a probability density function describing our observed data or -an hypothetical function describing the relation between the independent variables **`X`** and the single dependent variable `Y`. -We can have an arbitrary number `k` of independent variables. For example, when fitting a `k`-dimensional histogram, -the independent variables **`X`** are the bin center coordinates and `Y` is the bin weight. - -The model function needs to be expressed as function of some unknown parameters. The fitting will find the best parameter value to describe -the observed data. - -We can use the ROOT **`TF1`** class, the parametric function class, to describe the model function. However the `ROOT::Fit::Fitter` class, to be independent of the ROOT *`Hist`* library, -takes as input a more general parametric function object, the interface (abstract) class `ROOT::Math::IParametricFunctionMultiDim`, which describe a generic one or multi-dimensional function -with parameters. This interface extends the abstract class `ROOT::Math::IBaseFunctionMultiDim`, with methods to set/retrieve parameter values and to evaluate the function given the -independent vector of values **`X`** and vector of parameters `P`. -More information about the different `ROOT::Math` function interfaces is available in the Mathematical Library chapter. - -An end-user can convert a **`TF1`** object in a `ROOT::Math::IParametricFunctionMultiDim`, using the wrapper class `ROOT::Math::WrapperMultiTF1`: - -``` {.cpp} - TF1 * f1 = new TF1("f1","gaus"); - ROOT::Math::WrappedMultiTF1 fitFunction(f1, f1->GetNdim() ); - ROOT::Fit::Fitter fitter; - fitter.SetFunction( fitFunction, false); -``` - -When creating the wrapper, the parameter values stored in **`TF1`** will be copied in the `ROOT::Math::WrappedMultiTF1` object. -The function object representing the model function is given to the `ROOT::Fitter` class using the `Fitter::SetFunction` method. - -The user has also the possibility to provide a function object, which implements the derivatives of the function with respect -to the parameters. -This information might be useful for some types of fits. In this case he needs to provide the function object as a class deriving from the -`ROOT::Math::IParametricGradFunctionMultiDim` interface. -Note that the wrapper class `ROOT::Math::WrappedMultiTF1` implements also the gradient interface, using internally `TF1::GradientPar`, -which is based on numerical differentiation, apart for the case of linear functions (i.e. when `TF1::IsLinear()` is `true`). -The parameter derivatives of the model function can be useful to some minimization algorithms, such as Fumili. -However, in general is better to leave the minimization algorithm (e.g. Minuit) to compute the needed derivatives using its own customised -numerical differentiation algorithm. -In order to not provide to the fitter the parameter derivatives, we explicitly passed in `Fitter::SetFunction` a `false` value. - -### Fit Configuration - -The configuration of the fit is done via the `ROOT::Fit::FitConfig` class and its contained `ROOT::Fit::ParameterSettings` class. -These are the possible allowed fit configurations: - - - setting the initial values of the parameters; - - setting the parameter step sizes; - - setting eventual parameter bounds; - - setting the minimizer library and the particular algorithm to use; - - setting different minimization options (print level, tolerance, max iterations, etc...) - - setting the type of parameter errors to compute (parabolic error, Minos errors, re-normalize errors using fitted chi2 values) - - -The initial parameter values can be set directly in the input model function object. -However, for setting parameter bounds and step sizes to values different than the automatically computed ones, one needs to use the `ROOT::Fit::ParameterSetting` class. -This example code will set the lower/upper bounds for the first parameter and a lower bound for the second parameter - -``` {.cpp} - fitter.SetFunction( fitFunction, false); - fitter.Config().ParSettings(0).SetLimits(0,1.E6); - fitter.Config().ParSettings(2).SetLowerLimit(0); -``` - -Note that a `ROOT::Fit::ParameterSettings` objects exists for each fit parameter and it created by the `ROOT::Fit::FitConfig` class, after the model function has been set in the Fitter. -Only when the function is set, the number of parameter is known and -automatically the `FitConfig` creates the corresponding `ParameterSetting` objects. - -When fitting, different minimizer can be used. The can be implemented in different libraries and loaded ar run time by the plug-in manager system of ROOT. -Each different minimizer (e.g. *Minuit, Minuit2, Fumili,* etc.) consists of a different implementation of the `ROOT::Math::Minimizer` interface. -Within the same minimizer, thus within the same class implementing the `Minimizer` interface, different algorithms can exist. -For example in the case of Minuit, we have *Migrad, Simplex* or *Minimize*. The minimizer and its corresponding algorithm, when available, -can be set by using the function `FitConfig::SetMinimizer("minimizerName")` or by using directly the `ROOT:Math::MinimizerOptions` class. - -If the requested minimizer is not available in ROOT, the default one is used. The default minimizer type and algorithm can be specified by using the -static function `ROOT::Math::MinimizerOptions::SetDefaultMinimizer("minimizerName")` - - -### Minimizer Libraries and Algorithms - -The list of available minimizer libraries currently available in ROOT, with their corresponding available algorithms is the following one. -Some minimizers (e.g. *Minuit*) contain several algorithms that the user can -choose. Others are based on a single algorithm (e.g. *Fumili*) - - - - **`Minuit`** (library *libMinuit*). Old version of Minuit, based on the `TMinuit` class. The list of possible algorithms are: - - *`Migrad`* (default one) - - *`Simplex`* - - *`Minimize`* (it is a combination of Migrad and Simplex) - - *`MigradImproved`* - - *`Scan`* - - *`Seek`* - - - - **`Minuit2`** (library *libMinuit2*). New C++ version of Minuit. The list of possible algorithm is : - - *`Migrad`* (default) - - *`Simplex`* - - *`Minimize`* - - *`Scan`* - - *`Fumili`* . This is the same algorithm of `TFumili`, but implemented in the Minuit2 library. - - - **`Fumili`**. Implement a dedicated minimization algorithm for least-square and likelihood fits. It has requirements on the type of method function to be used. - No specific algorithm exists - - - **`GSLMultiMin`** (library *libMathMore*). Minimizer based on the Multidimensional Minimization routines of the Gnu Scientific Library (GSL). The list of available algorithms is - - *`BFGS2`* (default) : second version of the vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm; - - *`BFGS`* : old version of the vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm; - - *`ConjugateFR`* : Fletcher-Reeves conjugate gradient algorithm; - - *`ConjugatePR`* : Polak-Ribiere conjugate gradient algorithm; - - *`SteepestDescent`*: steepest descent algorithm; - - - **`GSLMultiFit`** (library *libMathMore*). Minimizer based on the Non-Linear Least-Square routines of GSL. This minimizer can be used only for least-square fits. - - - **`GSLSimAn`** (library *libMathMore*). Minimizer based on simulated annealing. - - - **`Genetic`** (library *libGenetic*). Genetic minimizer based on an algorithm implemented in the *TMVA* package. - -Each minimizer can be configured using the `ROOT::Math::MinimizerOptions` class. The list of possible option that can be set are: - -* *Minimizer type* (`MinimizerOptions::SetMinimizerType(const char *)`) . -* *Minimizer algorithm* (`MinimizerOptions::SetMinimizerAlgorithm(const char *)`). -* *Print Level* (`MinimizerOptions::SetPrintLevel(int )`) to set the verbose printing level (default is 0). -* *Tolerance* (`MinimizerOptions::SetTolerance(double )`) tolerance used to control the iterations. -* *Maximum number of function calls* (`MinimizerOptions::SetMaxFunctionCalls(int )`). -* *Maximum number of iterations* (`MinimizerOptions::SetMaxIterations(int )`). Note that this is not used by *Minuit* -* *FCN Upper value for Error Definition* (`MinimizerOptions::SetErrorDef(double )`). Value in the minimization function used to compute the parameter errors. - The default is to get the uncertainties at the 68% CL is a value of 1 for a chi-squared function minimization and 0.5 for a log-likelihood function. -* *Strategy* (`MinimizerOptions::SetStrategy(int )`), minimization strategy used. For each minimization strategy *Minuit* uses different configuration parameters - (e.g. different requirements in computing derivatives, computing full Hessian (strategy = 2) or an approximate version. The default is a value of 1. In this case the full Hessian matrix - is computed only after the minimization. -* *Precision* (`MinimizerOptions::SetPrecision(double )`). Precision value in the evaluation of the minimization function. Default is numerical double precision. - -Note that not all the options are implemented by all the minimizers. -For example in *Minuit* is possible to set the maximum number of function calls, but not the maximum number of iterations. The Strategy and the Precision options apply instead only for *Minuit* (and -*Minuit2*). - -The class supports also setting global default values for the options, by using the static functions `MinimizerOptions::SetDefault...` (for example `MinimizerOptions::SetDefaultPrintLevel(int )`). The -static functions can be also used to set the minimizer options when using `TH1::Fit` or `TGraph::Fit`. -The list of the current option values can be inspected by using `MinimizerOptions::Print`. -```{.cpp} -ROOT::Math::MinimizerOptions() opt; -// print the default minimizer option values -opt.Print(); -``` - -In addition it is possible to provide extra options which might apply for a particular minimizer `MinimizerOptions::SetExtraOptions(const IOptions & )`. -See the documentation of the particular minimizer to use for the list of possible additional options available. - - -### Performing the Fit - -Here we have now all the required input ingredients for the fit, the data and the function to fit. -Depending on these we have now several different way to perform the fit, using the corresponding methods of the -`ROOT::Fit::Fitter` class and depending on the type of input data. - -#### Available fit methods - -* **Least-square fit**: `Fitter::LeastSquare(const BinData & )` or `Fitter::Fit(const Bindata &)`. It requires the user to pass a `BinData` object. It should be used when the data values follow a - Gaussian distribution. This fit method is implemented using the class `ROOT::Fit::Chi2FCN`. -* **Binned Likelihood fit** : `Fitter::LikelihoodFit(const Bindata & )`. The user needs to pass a `BinData` object. It should be used when the data values follow a Poisson or a multinomial -distribution. The Poisson case (extended fit) is the default and in this case the function normalization is also fit to the data. The Multi-nominal case can be selected by passing the optional -*extended* boolean flag as *false*. This method is implemented by the class `ROOT::Fit:::PoissonLikelihoodFCN`. -* **Un-Binned likelihood fit**: `Fitter::LikelihoodFit(const UnBindata &)`. The user needs to pass an `UnBinData` object. By default the fit is not extended (i.e. the normalization is not fitted to the -data). As above the user can select an extended likelihood fit by passing the optional -*extended* boolean flag as *true*. This method is implemented using the class `LogLikelihoodFCN` -* **Linear Fit**: A linear fit can be selected (no iterative minimization is needed in this case, but using linear algebra algorithms from the *Matrix* library), if the model function is linear in the - parameters. - -#### Customised Fit methods - -Above we described the pre-defined methods used for fitting. A user can also implement its own fitting methods, thus its version of the chi-square or likelihood function he wants to minimize. -In this case, the user does not really need to build as input a `ROOT::Fit` data set and model function as we described before. He can implements its own version of the method function using on its own -data set objects and functions. - -In this case `ROOT::Fit::Fitter::SetFCN` is used to set the method function and `ROOT::Fit::FitFCN` is used for fitting. The method function can be passed also in `ROOT::Fit::FitFCN`, but in this -case a previously defined fitting configuration is used. - -The possible type of method functions that are based in `ROOT::Fit::Fitter::SetFCN` are: - -* A generic functor object implementing `operator()(const double * p)` where **`p`** is the parameter vectors. In this case one needs to pass the number of parameters, - the function object and optionally a vector of initial parameter values. Other optional parameter include the size of the data sets and a flag specifying if it is a chi2 (least-square fit). - In the last two parameters are given, the `chi2/ndf` can be computed after fitting the data. -``` {.cpp} -template -bool Fitter::SetFCN(unsigned int npar, Function & f, - const double * initialParameters = 0, - unsigned int dataSize=0, bool isChi2Fit = false) -``` - -* A function object implementing the `ROOT::Math::IBaseFunctionMultiDim` interface: -``` {.cpp} -bool Fitter::SetFCN(const ROOT::Math::IBaseFunctionMultiDim & f, - const double * initialParameters = 0, - unsigned int dataSize=0, bool isChi2Fit = false) -``` - -* A function object implementing the `ROOT::Math::FitMethodFunction` interface. This is an interface class extending -the `ROOT::Math::IBaseFunctionMultiDim` with some extra functionality which can be used when fitting. -This extra functionality is required by dedicated fitting algorithms like *Fumili* or *GSLMultiFit*. -``` {.cpp} -bool Fitter::SetFCN(const ROOT::Math::FitMethodFunction & f, - const double * initialParameters = 0, unsigned int dataSize=0) -``` - -* A old-Minuit like FCN interface (i.e. a free function with the signature `fcn(int &npar, double *gin, double &f, double *u, int flag)`. -``` {.cpp} -typedef void(* MinuitFCN)(int &npar, double *gin, double &f, double *u, int flag) -bool Fitter::SetFCN(MinuitFCN fcn, int npar, - const double * initialParameters = 0, - unsigned int dataSize=0, bool isChi2Fit = false) -``` - -### Fit Result - -The result of the fit is contained in the `ROOT::Fit::Result` object. A reference to the result object is obtained with the function -`Fitter::Result()`. -The `ROOT::Fit::FitResult` class provides an API for retrieving parameter values, errors, covariance and correlation matrix from the fit, -minimum chi2/likelihood values, etc... - -A `FitResult::Print` method is also available to print the result of the fit. - -The class has a self-explanatory API so, see its reference documentation for the possible information available after the fit. - -One extra functionality offered by `ROOT::Fit::FitResult` is the possibility to compute the confidence intervals of the function after the fit. -The function `ROOT::Fit::FitResult::GetConfidenceInterval` given an input data sets (e.g. a `BinData` object) and a confidence level value (e.g. 68%) -computes the lower/upper band values of the model function at the given data points. - -### TFitResult - -`TFitResult` is a class deriving from `ROOT::Fit::Result` and providing in addition some convenient methods to return a -covariance or correlation matrix as a `TMatrixDSym` object. In addition `TFitResult` derives from `TNamed` and can be conveniently -stored in a file. - -When fitting an histogram ( a **`TH1`** object) or a graph (a `TGraph` object) it is possible to return a `TFitResult` via the `TFitResultPtr` object, -which behaves as a smart pointer to a `TFitResult`. -`TFitResultPtr` is the return object by `TH1::Fit` or `TGraph::Fit`. -By default the TFitResultPtr contains only the status of the fit and can be obtained by an automatic conversion of the TFitResultPtr to an integer. - -If the fit option *`S`* is instead used, `TFitResultPtr` contains the `TFitResult` and behaves as a smart -pointer to it. This is an example: - -``` {.cpp} -int fitStatus = hist->Fit(myFunction); // TFitResultPtr contains only the fit status - -TFitResultPtr r = hist->Fit(myFunction,"S"); // TFitResultPtr contains the TFitResult -TMatrixDSym cov = r->GetCovarianceMatrix(); // to access the covariance matrix -Double_t chi2 = r->Chi2(); // to retrieve the fit chi2 -Double_t par0 = r->Parameter(0); // retrieve the value for the parameter 0 -Double_t err0 = r->ParError(0); // retrieve the error for the parameter 0 -r->Print("V"); // print full information of fit including covariance matrix -r->Write(); // store the result in a file -``` - -## The Minimization packages - -As explained before various minimization packages can be used when fitting in ROOT. -We have seen before how to configure the `Fitter` class to use different minimization packages -and different minimization options. -When using the `Fit` method the minimization package (and its options) can be selected using the -static methods of the `ROOT::Math::MinimizerOptions` class. -For example to select `Minuit2` instead of `Minuit` for fitting an histogram do: - -``` {.cpp} -ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2"); -// fit the histogram histo with the gaussian pre-defined function -histo->Fit("gaus"); -``` - -In the following we will give some brief description of the minimization packages. -The packages all implement the `ROOT::Math::Minimizer` interface which can be use for -finding the minimum of a multi-dimensional function. -The interface is documented in the Mathematical Library Chapter. - -In addition packages like Minuit or Minuit2 provide their own interfaces. - -## MINUIT (Old TMInuit Version) - - -This package was originally written in FORTRAN by Fred James and part -of `PACKLIB` (patch D506). It has been converted to a C++ class by -René Brun. The current implementation in C++ is a straightforward -conversion of the original FORTRAN version. The main changes are: - -- The variables in the various `Minuit` labeled common blocks have - been changed to the **`TMinuit`** class data members - -- The internal arrays with a maximum dimension depending on the - maximum number of parameters are now data members' arrays with a - dynamic dimension such that one can fit very large problems by - simply initializing the **`TMinuit`** constructor with the maximum - number of parameters - -- The include file `Minuit.h` has been commented as much as possible - using existing comments in the code or the printed documentation - -- The original `Minuit` subroutines are now member functions - -- Constructors and destructor have been added - -- Instead of passing the `FCN` function in the argument list, the - addresses of this function is stored as pointer in the data - members of the class. This is by far more elegant and flexible in - an interactive environment. The member function `SetFCN` can be - used to define this pointer - -- The ROOT static function `Printf` is provided to replace all - format statements and to print on currently defined output file - - -- The functions `SetObjectFit/GetObjectFit` can be used inside the - `FCN` function to set/get a referenced object instead of using - global variables - -- By default `fGraphicsMode` is true. When calling the `Minuit` - functions such as `mncont`, `mnscan`, or any `Minuit` command - invoking `mnplot`, `TMinuit::mnplot()` produces a **`TGraph`** - object pointed by `fPlot`. One can retrieve this object with - **`TMinuit`**`::GetPlot().` For example: - -``` {.cpp} - h->Fit("gaus"); - gMinuit->Command("SCAn 1"); - TGraph *gr = (TGraph*)gMinuit->GetPlot(); - gr->SetMarkerStyle(21); - gr->Draw("alp"); -``` - -- To set `Minuit` in no graphics mode, call - -``` {.cpp} - gMinuit->SetGraphicsMode(kFALSE); -``` - -### Basic Concepts of Minuit - - -The `Minuit` package acts on a multi parameter FORTRAN function to -which one must give the generic name `FCN`. In the ROOT -implementation, the function `FCN` is defined via the `Minuit` -`SetFCN` member function when an histogram fitting is invoked. The -value of `FCN` will in general depend on one or more variable -parameters. - - -### The Transformation of Limited Parameters - - -For variable parameters with limits, `Minuit` uses the following -transformation: - -`Pint = arcsin(2((Pext-a)/(b-a))-1) ` - -`Pext = a+((b-a)/(2))(sinPint+1)` - -so that the internal value `Pint` can take on any value, while the -external value Pext can take on values only between the lower limit a -and the ext upper limit b. Since the transformation is necessarily -non-linear, it would transform a nice linear problem into a nasty -non-linear one, which is the reason why limits should be avoided if -not necessary. In addition, the transformation does require some -computer time, so it slows down the computation a little bit, and more -importantly, it introduces additional numerical inaccuracy into the -problem in addition to what is introduced in the numerical calculation -of the FCN value. The effects of non-linearity and numerical round off -both become more important as the external value gets closer to one of -the limits (expressed as the distance to nearest limit divided by -distance between limits). The user must therefore be aware of the fact -that, for example, if they put limits of (0, 1010) on a parameter, then -the values 0.0 and 1. 0 will be indistinguishable to the accuracy of -most machines. - -The transformation also affects the parameter error matrix, of course, -so Minuit does a transformation of the error matrix (and the -''parabolic'' parameter errors) when there are parameter limits. Users -should however realize that the transformation is only a linear -approximation, and that it cannot give a meaningful result if one or -more parameters is very close to a limit, where -$\frac{\partial Pext}{\partial Pint} \neq 0$. Therefore, it is -recommended that: - -- Limits on variable parameters should be used only when needed in - order to prevent the parameter from taking on unphysical values - -- When a satisfactory minimum has been found using limits, the - limits should then be removed if possible, in order to perform or - re-perform the error analysis without limits - -### How to Get the Right Answer from Minuit - - -`Minuit` offers the user a choice of several minimization algorithms. -The `MIGRAD` algorithm is in general the best minimized for nearly all -functions. It is a variable-metric method with inexact line search, a -stable metric updating scheme, and checks for positive-definiteness. -Its main weakness is that it depends heavily on knowledge of the first -derivatives, and fails miserably if they are very inaccurate. - -If parameter limits are needed, in spite of the side effects, then the -user should be aware of the following techniques to alleviate problems -caused by limits: - -#### Getting the Right Minimum with Limits - -If MIGRAD converges normally to a point where no parameter is near one -of its limits, then the existence of limits has probably not prevented -`Minuit` from finding the right minimum. On the other hand, if one or -more parameters is near its limit at the minimum, this may be because -the true minimum is indeed at a limit, or it may be because the -minimized has become ''blocked'' at a limit. This may normally happen -only if the parameter is so close to a limit (internal value at an odd -multiple of $\pm \frac{\pi}{2}$ that `Minuit` prints a warning to this -effect when it prints the parameter values. The minimized can become -blocked at a limit, because at a limit the derivative seen by the -minimized $\frac{\partial F}{\partial Pint}$ is zero no matter what the real -derivative $\frac{\partial F}{\partial Pext}$ is. - -$$ -\left(\frac{\partial F}{\partial Pint}\right) = -\left(\frac{\partial F}{\partial Pext}\right) -\left(\frac{\partial Pext}{\partial Pint}\right) = -\left(\frac{\partial F}{\partial Pext}\right) = 0 -$$ - -#### Getting the Right Parameter Errors with Limits - -In the best case, where the minimum is far from any limits, `Minuit` -will correctly transform the error matrix, and the parameter errors it -reports should be accurate and very close to those you would have got -without limits. In other cases (which should be more common, since -otherwise you would not need limits), the very meaning of parameter -errors becomes problematic. Mathematically, since the limit is an -absolute constraint on the parameter, a parameter at its limit has no -error, at least in one direction. The error matrix, which can assign -only symmetric errors, then becomes essentially meaningless. - -#### Interpretation of Parameter Errors - -There are two kinds of problems that can arise: the reliability of -`Minuit`'s error estimates, and their statistical interpretation, -assuming they are accurate. - -#### Statistical Interpretation - -For discussion of basic concepts, such as the meaning of the elements -of the error matrix, or setting of exact confidence levels see the -articles: - -- F.James. Determining the statistical Significance of experimental - Results. Technical Report DD/81/02 and CERN Report 81-03, CERN, - 1981 - -- W.T.Eadie, D.Drijard, F.James, M.Roos, and B.Sadoulet. - *Statistical Methods in Experimental Physics. North-Holland, 1971* - -### Reliability of Minuit Error Estimates - - -`Minuit` always carries around its own current estimates of the -parameter errors, which it will print out on request, no matter how -accurate they are at any given point in the execution. For example, at -initialization, these estimates are just the starting step sizes as -specified by the user. After a `HESSE` step, the errors are usually -quite accurate, unless there has been a problem. `Minuit`, when it -prints out error values, also gives some indication of how reliable it -thinks they are. For example, those marked `CURRENT GUESS ERROR` are -only working values not to be believed, and `APPROXIMATE ERROR` means -that they have been calculated but there is reason to believe that -they may not be accurate. - -If no mitigating adjective is given, then at least `Minuit` believes -the errors are accurate, although there is always a small chance that -`Minuit` has been fooled. Some visible signs that `Minuit` may have -been fooled: - -- Warning messages produced during the minimization or error - analysis - -- Failure to find new minimum - -- Value of EDM too big (estimated Distance to Minimum) - -- Correlation coefficients exactly equal to zero, unless some - parameters are known to be uncorrelated with the others - -- Correlation coefficients very close to one (greater than 0.99). - This indicates both an exceptionally difficult problem, and one - which has been badly parameterized so that individual errors are - not very meaningful because they are so highly correlated - -- Parameter at limit. This condition, signaled by a `Minuit` warning - message, may make both the function minimum and parameter errors - unreliable. See the discussion above ‘Getting the right parameter - errors with limits' - -The best way to be absolutely sure of the errors is to use -''independent'' calculations and compare them, or compare the -calculated errors with a picture of the function. Theoretically, the -covariance matrix for a ''physical'' function must be -positive-definite at the minimum, although it may not be so for all -points far away from the minimum, even for a well-determined physical -problem. Therefore, if `MIGRAD` reports that it has found a -non-positive-definite covariance matrix, this may be a sign of one or -more of the following: - -#### A Non-physical Region - -On its way to the minimum, `MIGRAD` may have traversed a region that -has unphysical behavior, which is of course not a serious problem as -long as it recovers and leaves such a region. - -#### An Underdetermined Problem - -If the matrix is not positive-definite even at the minimum, this may -mean that the solution is not well defined, for example that there are -more unknowns than there are data points, or that the parameterization -of the fit contains a linear dependence. If this is the case, then -`Minuit` (or any other program) cannot solve your problem uniquely. -The error matrix will necessarily be largely meaningless, so the user -must remove the under determinedness by reformulating the -parameterization. `Minuit` cannot do this itself. - -#### Numerical Inaccuracies - -It is possible that the apparent lack of positive-definiteness is due -to excessive round off errors in numerical calculations (in the user -function), or not enough precision. This is unlikely in general, but -becomes more likely if the number of free parameters is very large, or -if the parameters are badly scaled (not all of the same order of -magnitude), and correlations are large. In any case, whether the -non-positive-definiteness is real or only numerical is largely -irrelevant, since in both cases the error matrix will be unreliable -and the minimum suspicious. - -#### An Ill-posed Problem - -For questions of parameter dependence, see the discussion above on -positive-definiteness. Possible other mathematical problems are the -following: - -- Excessive numerical round off - be especially careful of - exponential and factorial functions which get big very quickly and - lose accuracy. - -- Starting too far from the solution - the function may have - unphysical local minima, especially at infinity in some variables. - - - -## Minuit2 Package - - -`Minuit2` is a new object-oriented implementation, written in C++, of -the popular `MINUIT` minimization package. Compared with the -**`TMinuit`** class, which is a direct conversion from FORTRAN to C++, -`Minuit2` is a complete redesign and re-implementation of the package. -This new version provides all the functionality present in the old -FORTRAN version, with almost equivalent numerical accuracy and -computational performances. -Furthermore, it contains some fixes and small improvements and this new functionality: -* The possibility to set single side parameter limits -* the FUMILI algorithm (see the next paragraph "FUMILI Minimization Package"), -which is an optimized method for least square and log -likelihood minimizations. - -Minuit2 has been originally developed by M. -Winkler and F. James in the SEAL project. More information can be found -on the [MINUIT Web Site](MINUIT Web Site) and in particular at the -following documentation page at -. - -A detailed User Guide for Minuit2 exists, describing the API of the internal classes. -ROOT uses `Minuit2` for fitting via the `Minuit2Minimizer` class which implements -the `ROOT::Math::Minimizer` interface. - -`Minuit2` is also distributed as an independent package of ROOT and can be built -without any other dependency on the ROOT libraries. - -Examples on how to use the `Minuit2` and `Fumili2` plug-ins are provided -in the tutorials' directory `$ROOTSYS/tutorials/fit`: -`minuit2FitBench.C`, `minuit2FitBench2D.C` and `minuit2GausFit.C`. -More information on the classes and functions present in `Minuit2` is -available at -[online reference documentation](online reference documentation). - -Useful information on MINUIT and minimization in general is provided in the -following documents: - -F. James, *Minuit Tutorial on Function Minimization* ( -); F. James, *The -Interpretation of Errors in Minuit* ( -); - -## FUMILI Minimization Package - - -FUMILI is used to minimize Chi-square function or to search maximum of -likelihood function. Experimentally measured values $F_{i}$ are fitted -with theoretical -functions $f_{i}(\vec{x_{i}},\vec{\theta})$, where $\vec{x_{i}}$ are -coordinates, and $\vec{\theta}$ - vector of parameters. -For better convergence Chi-square function has to be the following form - -$$ -\frac{\chi^2}{2} = \frac{1}{2} \sum_{i=1}^{n} -\left(\frac{f_{i}(\vec{x_{i}},\vec{\theta}) - F_{i}} -{\sigma_{i}}\right)^{2} -$$ - -where $\sigma_{i}$ are errors of the measured function. The minimum -condition is: - -$$ -\frac{\partial \chi^{2}}{\partial \theta_{i}} = -\sum_{j=1}^{n} -\frac{1}{\sigma_{j}^{2}} . \frac{\partial f_{i}}{\partial \theta_{i}} -\left[ (\vec{x_{j}},\vec{\theta}) - - F_{j}\right] = 0, i = 1 ... m -$$ - -where $m$ is the quantity of parameters. Expanding left part of this -equation over parameter increments and retaining only linear terms one -gets - -$$ -\left(\frac{\partial \chi^{2}}{\theta_{i}}\right) -_{\theta = \vec{\theta}^{0}} + -\sum_{k} -\left(\frac{\partial^{2} \chi^{2}}{\partial \theta_{i} -\partial \theta_{k}}\right) -_{\theta = \vec{\theta}^{0}} . (\theta_{k} - \theta_{k}^{0}) = 0 -$$ - -here $\vec{\theta}^{0}$ is some initial value of parameters. In -general case: - -$$ -{\frac{\partial^2\chi^2}{\partial\theta_i\partial\theta_k}}= -\sum^n_{j=1}{\frac{1}{\sigma^2_j}} -{\frac{\partial f_j}{\theta_i}} {\frac{\partial f_j}{\theta_k}} + -\sum^n_{j=1}{\frac{(f_j - F_j)}{\sigma^2_j}}\cdot -{\frac{\partial^2f_j}{\partial\theta_i\partial\theta_k}} -$$ - -In FUMILI algorithm for second derivatives of Chi-square approximate -expression is used when last term in previous equation is discarded. -It is often done, not always wittingly, and sometimes causes troubles, -for example, if user wants to limit parameters with positive values by -writing down $\theta_i^2$ instead of $\theta_i$. FUMILI will fail if -one tries minimize $\chi^2 = g^2(\vec\theta)$ where g is arbitrary -function. - -Approximate value is: - -$$ -{\frac{\partial^2\chi^2}{\partial\theta_i\partial\theta_k}}\approx Z_{ik}= -\sum^n_{j=1}{\frac{1}{\sigma^2_j}}{\frac{\partial f_j}{\theta_i}} -{\frac{\partial f_j}{\theta_k}} -$$ - -Then the equations for parameter increments are: - -$$ -\left(\frac{\partial\chi^2}{\partial\theta_i}\right)_ -{\vec\theta={\vec\theta}^0} +\sum_k Z_{ik}\cdot(\theta_k-\theta^0_k) = - 0, \qquad i=1\ldots m -$$ - -Remarkable feature of algorithm is the technique for step restriction. -For an initial value of parameter ${\vec\theta}^0$ a parallelepiped -$P_0$ is built with the center at ${\vec\theta}^0$ and axes parallel -to coordinate axes $\theta_i$. The lengths of parallelepiped sides -along i-th axis is $2b_i$, where $b_i$ is such a value that the -functions $f_j(\vec\theta)$ are quasi-linear all over the -parallelepiped. - -FUMILI takes into account simple linear inequalities in the form: - -$$ \theta_i^{min}\le\theta_i\le\theta^{max}_i$$ - -They form parallelepiped $P$ ($P_0$ may be deformed by $P$). Very -similar step formulae are used in FUMILI for negative logarithm of -the likelihood function with the same idea - linearization of function -argument. - - - -## Neural Networks - - -### Introduction - - -Neural Networks are used in various fields for data analysis and -classification, both for research and commercial institutions. Some -randomly chosen examples are image analysis, financial movements' -predictions and analysis, or sales forecast and product shipping -optimization. In particles physics neural networks are mainly used for -classification tasks (signal over background discrimination). A vast -majority of commonly used neural networks are multilayer perceptrons. -This implementation of multilayer perceptrons is inspired from the -`MLPfit` package, which remains one of the fastest tools for neural -networks studies. - -### The MLP - - -The multilayer perceptron is a simple feed-forward network with the -following structure showed on the left. - -![](pictures/0300008D.png) - -It is made of neurons characterized by a bias and weighted links in -between - let's call those links synapses. The input neurons receive -the inputs, normalize them and forward them to the first hidden layer. -Each neuron in any subsequent layer first computes a linear -combination of the outputs of the previous layer. The output of the -neuron is then function of that combination with f being linear for -output neurons or a sigmoid for hidden layers. - -Such a structure is very useful because of two theorems: - -1- A linear combination of `sigmoids` can approximate any continuous -function. - -2- Trained with `output=1` for the signal and 0 for the background, -the approximated function of inputs `X` is the probability of signal, -knowing `X`. - -### Learning Methods - - -The aim of all learning methods is to minimize the total error on a -set of weighted examples. The error is defined as the sum in quadrate, -divided by two, of the error on each individual output neuron. In all -methods implemented in this library, one needs to compute the first -derivative of that error with respect to the weights. Exploiting the -well-known properties of the derivative, one can express this -derivative as the product of the local partial derivative by the -weighted sum of the outputs derivatives (for a neuron) or as the -product of the input value with the local partial derivative of the -output neuron (for a synapse). This computation is called -"back-propagation of the errors". Six learning methods are -implemented. - -#### Stochastic Minimization - -This is the most trivial learning method. The Robbins-Monro stochastic -approximation is applied to multilayer perceptrons. The weights are -updated after each example according to the formula: - -$$ -w_{ij}(t+1) = w_{ij}(t) + \Delta w_{ij}(t) -$$ - -with: - -$$ -\Delta w_{ij}(t) = - \eta \left( -\frac{\partial e_p}{\partial w_{ij}} + \delta \right) + -\epsilon \Delta w_{ij}(t-1) -$$ - -The parameters for this method are `Eta`, `EtaDecay`, `Delta` and -`Epsilon`. - -#### Steepest Descent With Fixed Step Size (Batch Learning) - -It is the same as the stochastic minimization, but the weights are -updated after considering all the examples, with the total derivative -`dEdw`. The parameters for this method are `Eta`, `EtaDecay`, `Delta` -and `Epsilon`. - -#### Steepest Descent Algorithm - -Weights are set to the minimum along the line defined by the gradient. -The only parameter for this method is `Tau`. Lower `Tau` = higher -precision = slower search. A value `Tau=3` seems reasonable. - -#### Conjugate Gradients With the Polak-Ribiere Updating Formula - -Weights are set to the minimum along the line defined by the conjugate -gradient. Parameters are `Tau` and `Reset`, which defines the epochs -where the direction is reset to the steepest descent (estimated by -using the Polak-Ribiere formula). - -#### Conjugate Gradients With the Fletcher-Reeves Updating Formula - -Weights are set to the minimum along the line defined by the conjugate -gradient. Parameters are `Tau` and `Reset`, which defines the epochs -where the direction is reset to the steepest descent (estimated by -using the Fletcher-Reeves formula). - -#### The Broyden, Fletcher, Goldfarb, Shanno (BFGS) Method - -It implies the computation of a `NxN` matrix, but seems more powerful -at least for less than 300 weights. Parameters are `Tau` and `Reset`, -which defines the epochs where the direction is reset to the steepest -descent. - -### Using the Network - - -Neural network are build from a set of "samples". A sample is a set of -values defining the inputs and the corresponding output that the -network should ideally provide. In ROOT this is a **`TTree`** entry. -The first thing to be decided is the network layout. This layout is -described in a string where the layers are separated by semicolons. -The input/output layers are defined by giving the expression for each -neuron, separated by comas. Hidden layers are just described by the -number of neurons. - -In addition, input and output layer formulas can be preceded by '@' -(e.g. "@out") if one wants to normalize the corresponding value. Also, -if the string ends with '`!`', output neurons are set up for -classification, i.e. with a sigmoid (1 neuron) or softmax (more -neurons) activation function. - -Many questions on the good usage of neural network, including rules of -dumb to determine the best network topology are addressed at - - -``` {.cpp} - // a simple network: 2 inputs, 10 hidden and 1 normalized - // output neuron - TMultiLayerPerceptron network("r,z:10:@Br",tree); -``` - -Expressions are evaluated as for `TTree::Draw()`. Input and outputs -are taken from the **`TTree`** associated with the network. This -**`TTree`** can be given as argument of the constructor or defined -later with `TMultiLayerPerceptron::SetData()`. Events can also be -weighted. The weight expression can be given in the constructor or set -later with the method `SetWeight()` of the class -**`TMultiLayerPerceptron`**. Two datasets must be defined before -learning the network: a training dataset that is used when minimizing -the error, and a test dataset that will avoid bias. Those two datasets -can be built aside and then given to the network, or can be built from -a standard expression. By default, half of the events are put in both -datasets. - -``` {.cpp} - // a more complex 4:8:1 network - // the ptsumf branch is used as weigh; - // default event lists are explicit - TMultiLayerPerceptron network("m,pt,acol,acopl:8:type","pt",tree, - "Entry$%2","Entry$/2"); -``` - -The method `TMultiLayerPerceptron::SetLearningMethod()` defines the -learning method. Learning methods are: - -``` -TMultiLayerPerceptron::kStochastic, -TMultiLayerPerceptron::kBatch, -TMultiLayerPerceptron::kSteepestDescent, -TMultiLayerPerceptron::kRibierePolak, -TMultiLayerPerceptron::kFletcherReeves, -TMultiLayerPerceptron::kBFGS // default -``` - -The training can start with -`TMultiLayerPerceptron::Train(Int_t nepoch,Option_t* options).` The -first argument is the number of epochs while option is a string that -can contain "`text`" (simple text output), "`graph`" (evaluating -graphical training curves), "`update` `=` `X`" (step for the -text/graph output update) or "`+`" (will skip the randomization and -start from the previous values). All combinations are available. - -``` {.cpp} - network.Train(1000,"text,graph,update=10"); // full output every - // 10 epochs - network.Train(100,"text,+"); // 100 more epochs - //starts with existing weights -``` - -The weights can be saved to a file (`DumpWeights`) and then reloaded -(`LoadWeights`) to a new compatible network. The output can also be -evaluated (`Evaluate`) for a given output neuron and an array of -double input parameters or the network can be exported (`Export`) as a -standalone code. Up to now, this is only as a C++ or PYTHON class, but -other languages could be implemented. - -### Examples - - -An example of how to use **`TMultiLayerPerceptron`** is the macro -`mlpHiggs.C` in \$ROOTSYS/tutorials. Using some standard simulated -information that could have been obtained at `LEP`, a neural network -is build, which can make the difference between `WW` events and events -containing a Higgs boson. Starting with a **`TFile`** containing two -**`TTree`**s: one for the signal, the other for the background, a -simple script is used: - -``` {.cpp} - void mlpHiggs(Int_t ntrain=100) { - if (!gROOT->GetClass("TMultiLayerPerceptron")) - gSystem->Load("libMLP"); - // prepare inputs - the 2 trees are merged into one, and a - // "type" branch, equal to 1 for the signal and 0 for the - // background is added - TFile input("mlpHiggs.root"); - TTree *signal = (TTree *)input.Get("sig_filtered"); - TTree *background = (TTree *)input.Get("bg_filtered"); - TTree *simu = new TTree("MonteCarlo", - "Filtered Monte Carlo Events"); - ... -``` - -Since the input is a **`TTree`** and we are starting from two -different **`TTree`**s (with different names), they are first merged -into one, and a "`type`" branch is added, that says whether there is -a signal or a background event. Those irrelevant details are skipped -here. - -``` {.cpp} - ... - TMultiLayerPerceptron *mlp = new TMultiLayerPerceptron( - "msumf,ptsumf, acolin, acopl:8:type","ptsumf",simu, - "Entry$%2","Entry$/2"); - mlp->Train(ntrain, "text,graph,update=10"); -``` - -The neural network is instantiated and trained. "`ptsumf`" is used as -a weight, and the standard event lists are explicit. The network that -is then build has four input neurons, eight additional ones in the -only hidden layer and one single output neuron. - -``` {.cpp} - // Use the NN to plot the results for each sample - TH1F *bg = new TH1F("bgh","NN output",50,-.5,1.5); - TH1F *sig = new TH1F("sigh","NN output",50,-.5,1.5); - bg->SetDirectory(0); - sig->SetDirectory(0); - Double_t params[4]; - for (i = 0; i < background->GetEntries(); i++) { - background->GetEntry(i); - params[0] = msumf; params[1] = ptsumf; - params[2] = acolin; params[3] = acopl; - bg->Fill(mlp->Evaluate(0,params)); - } - for (i = 0; i < signal->GetEntries(); i++) { - signal->GetEntry(i); - params[0] = msumf; - params[1] = ptsumf; - params[2] = acolin; - params[3] = acopl; - sig->Fill(mlp->Evaluate(0,params)); - } - TCanvas *cv = new TCanvas("NNout_cv","Neural net output"); - bg->SetFillStyle(3008); - bg->SetFillColor(kBlue); - sig->SetFillStyle(3003); - sig->SetFillColor(kRed); - bg->SetStats(0); - sig->SetStats(0); - bg->Draw(); - sig->Draw("same"); - TLegend *legend = new TLegend(.75,.80,.95,.95); - legend->AddEntry(bg,"Background(WW)"); - legend->AddEntry(sig,"Signal(Higgs)"); - legend->Draw(); -``` - -The neural net output is then used to display the final difference -between background and signal events. The figure "The neural net -output" shows this plot. - -![The neural net output](pictures/image144.png) - -As it can be seen, this is a quite efficient technique. As mentioned -earlier, neural networks are also used for fitting function. For some -application with a cylindrical symmetry, a magnetic field simulation -gives as output the angular component of the potential vector `A`, as -well as the radial and `z` components of the `B` field. - -One wants to fit those distributions with a function in order to plug -them into the `Geant` simulation code. Polynomial fits could be tried, -but it seems difficult to reach the desired precision over the full -range. One could also use a `spline` interpolation between known -points. In all cases, the resulting field would not be `C`-infinite. - -An example of output (for Br) is shown. First the initial function can -be seen as the target. Then, the resulting (normalized) neural net -output. In order to ease the learning, the "normalize output" was used -here. The initial amplitude can be recovered by multiplying by the -original RMS and then shifting by the original mean. - -![The original and the neural net for Br](pictures/image145.jpg) diff --git a/documentation/users-guide/FoldersTasks.md b/documentation/users-guide/FoldersTasks.md deleted file mode 100644 index 868907c521e5c..0000000000000 --- a/documentation/users-guide/FoldersTasks.md +++ /dev/null @@ -1,322 +0,0 @@ -# Folders and Tasks - - -## Folders - - -![](pictures/030000E1.png) - -A **`TFolder`** is a collection of objects -visible and expandable in the ROOT object browser. Folders have a name -and a title and are identified in the folder hierarchy by an "UNIX-like" -naming convention. The base of all folders is `//root`. It is visible at -the top of the left panel in the browser. The browser shows several -folders under `//root`. - -New folders can be added and removed to/from a folder. - -## Why Use Folders? - - -One reason to use folders is to reduce class dependencies and improve -modularity. Each set of data has a producer class and one or many -consumer classes. When using folders, the producer class places a -pointer to the data into a folder, and the consumer class retrieves a -reference to the folder. - -The consumer can access the objects in a folder by specifying the path -name of the folder. - -Here is an example of a folder's path name: - -`//root/Event/Hits/TCP` - -One does not have to specify the full path name. If the partial path -name is unique, it will find it; otherwise it will return the first -occurrence of the path. - -The first diagram shows a system without folders. The objects have -pointers to each other to access each other's data. Pointers are an -efficient way to share data between classes. However, a direct pointer -creates a direct coupling between classes. This design can become a very -tangled web of dependencies in a system with a large number of classes. - -![](pictures/020000E2.jpg) - -In the second diagram, a reference to the data is in the folder and the -consumers refer to the folder rather than each other to access the data. -The naming and search service provided by the ROOT folders hierarchy -provides an alternative. It loosely couples the classes and greatly -enhances I/O operations. In this way, folders separate the data from the -algorithms and greatly improve the modularity of an application by -minimizing the class dependencies. - -![](pictures/020000E3.jpg) - -In addition, the folder hierarchy creates a picture of the data -organization. This is useful when discussing data design issues or when -learning the data organization. The example below illustrates this -point. - -## How to Use Folders - - -Using folders means to build a hierarchy of folders, posting the -reference to the data in the folder by the producer, and creating a -reference to the folder by the user. - -### Creating a Folder Hierarchy - - -To create a folder hierarchy you add the top folder of your hierarchy to -`//root`. Then you add a folder to an existing folder with the -**`TFolder::AddFolder`** method. This method takes two parameters: the -name and title of the folder to be added. It returns a pointer of the -newly created folder. - -The code below creates the folder hierarchy shown in the browser. In -this macro, the folder is also added to the list of browsable. This way, -it is visible in the browser on the top level. - -``` {.cpp} -{ - // Add the top folder of my hierary to //root - TFolder *aliroot=gROOT->GetRootFolder()->AddFolder("aliroot", - "aliroot top level folders"); - // Add the hierarchy to the list of browsables - gROOT->GetListOfBrowsables()->Add(aliroot,"aliroot"); - - // Create and add the constants folder - TFolder *constants=aliroot->AddFolder("Constants", - "Detector constants"); - - // Create and add the pdg folder to pdg - TFolder *pdg = constants->AddFolder("DatabasePDG","PDG database"); - - // Create and add the run folder - TFolder *run = aliroot->AddFolder("Run","Run dependent folders"); - - // Create and add the configuration folder to run - TFolder *configuration = run->AddFolder("Configuration", - "Run configuration"); - - // Create and add the run_mc folder - TFolder *run_mc = aliroot->AddFolder("RunMC", - "MonteCarlo run dependent folders"); - - // Create and add the configuration_mc folder to run_mc - TFolder *configuration_mc = run_mc->AddFolder("Configuration", - "MonteCarlo run configuration"); -} -``` - -### Posting Data to a Folder (Producer) - - -![](pictures/030000E4.png) - -A **`TFolder`** can contain other folders as shown above or any -**`TObject`** descendents. In general, users will not post a single -object to a folder; they will store a collection or multiple collections -in a folder. For example, to add an array to a folder: - -``` {.cpp} -TObjArray *array; -run_mc->Add(array); -``` - -### Reading Data from a Folder (Consumer) - - -One can search for a folder or an object in a folder using the -`TROOT::FindObjectAny` method. It analyzes the string passed as its -argument and searches in the hierarchy until it finds an object or -folder matching the name. With `FindObjectAny`, you can give the full -path name, or the name of the folder. If only the name of the folder is -given, it will return the first instance of that name. A string-based -search is time consuming. If the retrieved object is used frequently or -inside a loop, you should save a pointer to the object as a class data -member. Use the naming service only in the initialization of the -consumer class. When a folder is deleted, any reference to it in the -parent or other folder is deleted also. - -``` {.cpp} - conf=(TFolder*)gROOT->FindObjectAny("/aliroot/Run/Configuration"); - // or ... - conf=(TFolder*)gROOT->FindObjectAny("Configuration"); -``` - -By default, a folder does not own the object it contains. You can -overwrite that with `TFolder::SetOwner`. Once the folder is the owner of -its contents, the contents are deleted when the folder is deleted. Some -ROOT objects are automatically added to the folder hierarchy. For -example, the following folders exist on start up: - -`//root/ROOT Files` with the list of open Root files - -`//root/Classes` with the list of active classes - -`//root/Geometries` with active geometries - -`//root/Canvases` with the list of active canvases - -`//root/Styles` with the list of graphics styles - -`//root/Colors` with the list of active colors - -For example, if a file `myFile.root` is added to the list of files, one -can retrieve a pointer to the corresponding **`TFile`** object with a -statement like: - -``` {.cpp} - TFile *myFile = (TFile*)gROOT->FindObjectAny( - "/ROOTFiles/myFile.root"); - //or... - TFile *myFile = (TFile*)gROOT->FindObjectAny("myFile.root"); -``` - -## Tasks - - -Tasks can be organized into a hierarchy and displayed in the browser. -The **`TTask`** class is the base class from which the tasks are -derived. To give task functionality, you need to subclass the -**`TTask`** class and override the `Exec` method. An example of -**`TTask`** subclasses` is $ROOTSYS/tutorials/MyTasks.cxx`. The script -that creates a task hierarchy and adds it to the browser is -\$`ROOTSYS/tutorials/tasks.C`. Here is a part of `MyTasks.cxx` that -shows how to subclass from **`TTask`**. - -``` {.cpp} -// A set of classes deriving from TTask see macro tasks.C. The Exec -// function of each class prints one line when it is called. -#include "TTask.h" -class MyRun : public TTask { -public: - MyRun() { ; } - MyRun(const char *name,const char *title); - virtual ~MyRun() { ; } - void Exec(Option_t *option=""); - ClassDef(MyRun,1) // Run Reconstruction task -}; - -class MyEvent : public TTask { -public: - MyEvent() { ; } - MyEvent(const char *name,const char *title); - virtual ~MyEvent() { ; } - void Exec(Option_t *option=""); - ClassDef(MyEvent,1) // Event Reconstruction task -}; -``` - -Later in `MyTasks.cxx`, we can see examples of the constructor and -overridden `Exec()` method: - -``` {.cpp} -ClassImp(MyRun) -MyRun::MyRun(const char *name,const char *title):TTask(name,title) -{ -... -} -void MyRun::Exec(Option_t *option) -{ - printf("MyRun executingn"); -} -``` - -Each **`TTask`** derived class may contain other **`TTasks`** that can -be executed recursively. In this way, a complex program can be -dynamically built and executed by invoking the services of the top level -task or one of its subtasks. The constructor of **`TTask`** has two -arguments: the name and the title. This script creates the task defined -above, and creates a hierarchy of tasks. - -``` {.cpp} -// Show the tasks in a browser. To execute a Task, select -// "ExecuteTask" in the context menu see also other functions in the -// TTask context menu, such as: -// -setting a breakpoint in one or more tasks -// -enabling/disabling one task, etc -void tasks() { - gROOT->ProcessLine(".L MyTasks.cxx+"); - - TTask *run = new MyRun("run","Process one run"); - TTask *event = new MyEvent("event","Process one event"); - TTask *geomInit = new MyGeomInit("geomInit", - "Geometry Initialisation"); - TTask *matInit = new MyMaterialInit("matInit", - "MaterialsInitialisation"); - TTask *tracker = new MyTracker("tracker","Tracker manager"); - TTask *tpc = new MyRecTPC("tpc","TPC Reconstruction"); - TTask *its = new MyRecITS("its","ITS Reconstruction"); - TTask *muon = new MyRecMUON("muon","MUON Reconstruction"); - TTask *phos = new MyRecPHOS("phos","PHOS Reconstruction"); - TTask *rich = new MyRecRICH("rich","RICH Reconstruction"); - TTask *trd = new MyRecTRD("trd","TRD Reconstruction"); - TTask *global = new MyRecGlobal("global","Global Reconstruction"); - - // Create a hierarchy by adding sub tasks - run->Add(geomInit); - run->Add(matInit); - run->Add(event); - event->Add(tracker); - event->Add(global); - tracker->Add(tpc); - tracker->Add(its); - tracker->Add(muon); - tracker->Add(phos); - tracker->Add(rich); - tracker->Add(trd); - - // Add the top level task - gROOT->GetListOfTasks()->Add(run); - - // Add the task to the browser - gROOT->GetListOfBrowsables()->Add(run); - new TBrowser; -} -``` - -![Tasks in the ROOT browser](pictures/030000E5.png) - -Note that the first line loads the class definitions in `MyTasks.cxx` -with ACLiC. ACLiC builds a shared library and adds the classes to the -Cling dictionary. See "Adding a Class with ACLiC". - -To execute a **`TTask`**, you call the `ExecuteTask` method. -`ExecuteTask` will recursively call: - -- the `TTask::Exec `method of the derived class; - -- the `TTask::ExecuteTasks` to execute for each task the list of its -subtasks; - -If the top level task is added to the list of ROOT browsable objects, -the tree of tasks can be seen in the ROOT browser. To add it to the -browser, get the list of browsable objects first and add it to the -collection. - -``` {.cpp} - gROOT->GetListOfBrowsables()->Add(run); -``` - -The first parameter of the `Add` method is a pointer to a **`TTask`**, -the second parameter is the string to show in the browser. If the string -is left out, the name of the task is used. - -After executing, the script above the browser will look like in this -figure. - -## Execute and Debug Tasks - - -The browser can be used to start a task, set break points at the -beginning of a task or when the task has completed. At a breakpoint, -data structures generated by the execution up this point may be -inspected asynchronously and then the execution can be resumed by -selecting the "`Continue`" function of a task. - -A task may be active or inactive (controlled by `TTask::SetActive`). -When a task is inactive, its sub tasks are not executed. A task tree may -be made persistent, saving the status of all the tasks. diff --git a/documentation/users-guide/Geometry.md b/documentation/users-guide/Geometry.md deleted file mode 100644 index d82fd33a95d5e..0000000000000 --- a/documentation/users-guide/Geometry.md +++ /dev/null @@ -1,4140 +0,0 @@ -# The Geometry Package -\index{Geometry} - -The new ROOT geometry package is a tool for building, browsing, -navigating and visualizing detector geometries. The code works -standalone with respect to any tracking Monte-Carlo engine; therefore, -it does not contain any constraints related to physics. However, the -navigation features provided by the package are designed to optimize -particle transport through complex geometries, working in correlation -with simulation packages such as GEANT3, GEANT4 and FLUKA. - -## Quick Start: Creating the "world" - -This chapter will provide a detailed description on how to build valid -geometries as well as the ways to optimize them. There are several -components gluing together the geometrical model, but for the time being -let us get used with the most basic concepts. - -The basic bricks for building-up the model are called -`volumes`**.**These represent the un-positioned pieces of the geometry -puzzle. The difference is just that the relationship between the pieces -is not defined by neighbors, but by `containment`. In other words, -volumes are put one inside another making an in-depth hierarchy. From -outside, the whole thing looks like a big pack that you can open finding -out other smaller packs nicely arranged waiting to be opened at their -turn. The biggest one containing all others defines the "`world`" of the -model. We will often call this `master reference system (MARS)`. Going -on and opening our packs, we will obviously find out some empty ones, -otherwise, something is very wrong... We will call these leaves (by -analogy with a tree structure). - -On the other hand, any volume is a small world by itself - what we need -to do is to take it out and to ignore all the rest since it is a -self-contained object. In fact, the modeller can act like this, -considering a given volume as temporary MARS, but we will describe this -feature later on. Let us focus on the biggest pack - it is mandatory to -define one. Consider the simplest geometry that is made of a single box. -Here is an example on how to build it: - -### Example 1: Creating the World - -We first need to load the geometry library. This is not needed if one -does `make map` in root folder. - -``` {.cpp} -root[] gSystem->Load("libGeom"); -``` - -Second, we have to create an instance of the geometry manager class. -This takes care of all the modeller components, performing several tasks -to insure geometry validity and containing the user interface for -building and interacting with the geometry. After its creation, the -geometry manager class can be accessed with the global -***`gGeoManager`***: - -``` {.cpp} -root[] new TGeoManager("world", "the simplest geometry"); -``` - -We want to create a single volume in our geometry, but since any volume -needs to have an associated medium, we will create a dummy one. You can -safely ignore the following lines for the time being, since materials -and media will be explained in detail later on. - -``` {.cpp} -root[] TGeoMaterial *mat = new TGeoMaterial("Vacuum",0,0,0); -root[] TGeoMedium *med = new TGeoMedium("Vacuum",1,mat); -``` - -We can finally make our volume having a box shape. Note that the world -volume does not need to be a box - it can be any other shape. Generally, -boxes and tubes are the most recommendable shapes for this purpose due -to their fast navigation algorithms. - -``` {.cpp} -root[] TGeoVolume *top=gGeoManager->MakeBox("Top",med,10.,10.,10.); -``` - -The default units are in centimeters. Now we want to make this volume -our world. We have to do this operation **before** closing the geometry. - -``` {.cpp} -root[] gGeoManager->SetTopVolume(top); -``` - -This should be enough, but it is not since always after defining some -geometry hierarchy, **`TGeo`** needs to build some optimization -structures and perform some checks. Note the messages posted after the -statement is executed. We will describe the corresponding operations -later. - -``` {.cpp} -root[] gGeoManager->CloseGeometry(); -``` - -Now we are really done with geometry building stage, but we would like -to see our simple world: - -``` {.cpp} -root[] top->SetLineColor(kMagenta); -root[] gGeoManager->SetTopVisible(); // the TOP is invisible -root[] top->Draw(); -``` - -### Example 2: A Geometrical Hierarchy Look and Feel - -Before going further, let us get a look and feel of interacting with the -modeller. For this, we will use one of the examples illustrating the -geometry package. To get an idea on the geometry structure created in -this example, just look at the link: -. You will -notice that this is a bit more complex that just creating the "world" -since several other volumes are created and put together in a hierarchy. -The purpose here is just to learn how to interact with a geometry that -is already built, but just few hints on the building steps in this -example might be useful. The geometry here represents the word ROOT that -is replicated in some symmetric manner. You might for instance ask some -questions after having a first look: - -***`Q:`*** "OK, I understand the first lines that load the libGeom library and create -a geometry manager object. I also recognize from the previous example the following -lines creating some materials and media, but what about the geometrical transformations below?" - -***`A:`*** As explained before, the model that we are trying to create -is a hierarchy of volumes based on ***`containment`***. This is -accomplished by ***`positioning`*** some volumes ***`inside`*** others. -Any volume is an un-positioned object in the sense that it defines only -a ***`local frame`*** (matching the one of its ***`shape`***). In order -to fully define the mother-daughter relationship between two volumes one -has to specify how the daughter will be positioned inside. This is -accomplished by defining a ***`local geometrical transformation`*** of -the daughter with respect to the mother coordinate system. These -transformations will be subsequently used in the example. - -***`Q:`*** "I see the lines defining the top level volume as in the previous example, -but what about the other volumes named REPLICA and ROOT?" - -***`A:`*** You will also notice that several other volumes are created -by using lines like: - -``` {.cpp} -TGeoVolume *someVolume = gGeoManager->MakeXXX("someName", -ptrMedium, /* parameters coresponding to XXX ...*/) -``` - -In the method above **`XXX`** represent some shape name (Box, Tube, -etc.). This is just a simple way of creating a volume having a given -shape in one-step (see also section: "Creating and Positioning -Volumes"). As for REPLICA and ROOT volumes, they are just some -***`virtual volumes`*** used for grouping and positioning together other -***`real volumes`***. See "Positioned Volumes (Nodes)". The same -structure represented by (a real or) a virtual volume can be -***`replicated`*** several times in the geometry. - -***`Q:`*** "Fine, so probably the real volumes are the ones composing the letters R, -O and T. Why one have to define so many volumes to make an R?" - -***`A:`*** Well, in real life some objects have much more complex shapes -that an ***`R`***. The modeller cannot just know all of them; the idea -is to make a complex object by using elementary building blocks that -have known shapes (called ***`primitive shapes`***). Gluing these -together in the appropriate way is the user responsibility. - -***`Q:`*** "I am getting the global picture but not making much out of it... There -are also a lot of calls to TGeoVolume::AddNode() that I do not understand." - -***`A:`*** A volume is positioned inside another one by using this -method. The relative geometrical transformation as well as a copy number -must be specified. When positioned, a volume becomes a ***`node`*** of -its container and a new object of the class **`TGeoNode`** is -automatically created. This method is therefore the key element for the -creation of a hierarchical link between two volumes. As it will be -described further on in this document, there are few other methods -performing similar actions, but let us keep things simple for the time -being. In addition, notice that there are some visualization-related -calls in the example followed by a final `TGeoVolume::Draw() `call for -the top volume. These are explained in details in the section -"Visualization Settings and Attributes". At this point, you will -probably like to see how this geometry looks like. You just need to run -the example and you will get the following picture that you can rotate -using the mouse; or you can zoom / move it around (see what the Help -menu of the GL window displays). - -``` {.cpp} -% root rootgeom.C -``` - -![](pictures/020001B1.jpg) - -Now let us browse the hierarchy that was just created. Start a browser -and double-click on the item simple1 representing the -***`gGeoManager`*** object. Note that right click opens the context menu -of the manager class where several global methods are available. - -``` {.cpp} -root[] new TBrowser; -``` - -![](pictures/020001B2.jpg) - -The folders `Materials`, `Media` and `Local transformations` are in fact -the containers where the geometry manager stores the corresponding -objects. The `Illegal overlaps` folder is empty but can be filled after -performing a geometry validity check (see section: "Checking the -Geometry"). If tracking is performed using **`TGeo`**, the folder -`Tracks` might contain user-defined tracks that can be -visualized/animated in the geometry context (see section: "Creating and -Visualizing Tracks"). Since for the time being we are interested more in -the geometrical hierarchy, we will focus on the last two displayed items -`TOP `and `TOP_1`. These are the top volume and the corresponding top -node in the hierarchy. - -Double clicking on the `TOP` volume will unfold all different volumes -contained by the top volume. In the right panel, we will see all the -volumes contained by `TOP` (if the same is positioned 4 times we will -get 4 identical items). This rule will apply to any clicked volume in -the hierarchy. Note that right clicking a volume item activates the -volume context menu containing several specific methods. We will call -the volume hierarchy developed in this way as the -`logical geometry graph`. The volume objects are nodes inside this graph -and the same volume can be accessed starting from different branches. - -On the other hand, the real geometrical objects that are seen when -visualizing or tracking the geometry are depicted in the `TOP_1` branch. -These are the nodes of the `physical` `tree` of positioned volumes -represented by **`TGeoNode`** objects. This hierarchy is a tree since a -node can have only one parent and several daughters. For a better -understanding of the hierarchy, have a look at -. - -Just close now the `X3D` window and focus at the wire frame picture -drawn in a pad. Activate Options/Event Status. Moving the mouse in the -pad, you will notice that objects are sometimes changing color to red. -Volumes are highlighted in this way whenever the mouse pointer is close -enough to one of its vertices. When this happens, the corresponding -volume is selected and you will see in the bottom right size of the ROOT -canvas its name, shape type and corresponding path in the physical tree. -Right clicking on the screen when a volume is selected will also open -its context menu (picking). Note that there are several actions that can -be performed both at view (no volume selected) and volume level. - -**`TView`** (mouse not selecting any volume): - -- Click-and-drag rotates the view. -- Pressing some keys perform different actions: -- J/K - zoom / unzoom -- H, L, U, I - move the viewpoint -- Right click + `SetParallel` `()/SetPerspective` `()` - switch from - parallel to perspective view. -- Right click + `ShowAxis()` - show coordinate axes. -- Right click + `Centered/Left/Side/Top` - change view direction. - -**`TGeoVolume`** (mouse selecting a volume): - -- Double click will focus the corresponding volume. -- Right click + `CheckOverlaps()` - run overlap checker on current - volume. -- Right click + `Draw` `()` - draw that volume according current - global visualization options -- Right click + `DrawOnly()`***` - `***draw only the selected volume. -- Right click + `InspectShape/Material()` - print info about shape or - material. -- Right click + `Raytrace()` - initiate a ray tracing algorithm on - current view. -- Right click + `RandomPoints/Rays()` - shoot random points or rays - inside the bounding box of the clicked volume and display only those - inside visible volumes. -- Right click + `Weight()` - estimates the weight of a volume within a - given precision. - -Note that there are several additional methods for visibility and line -attributes settings. - -## Materials and Tracking Media - -We have mentioned that volumes are the building blocks for geometry, but -they describe real objects having well defined properties. In fact, -there are just two of them: the material they are made from and their -geometrical `shape`. These have to be created before creating the volume -itself, so we will describe the bits and pieces needed for making the -geometry before moving to an architectural point of view. - -As far as materials are concerned, they represent the physical -properties of the solid from which a volume is made. Materials are just -a support for the data that has to be provided to the tracking engine -that uses this geometry package. Due to this fact, the -**`TGeoMaterial`** class is more like a thin data structure needed for -building the corresponding native materials of the Monte-Carlo tracking -code that uses **`TGeo`**. - -### Elements, Materials and Mixtures - -In order to make easier material and mixture creation, one can use the -pre-built table of elements owned by **`TGeoManager`** class: - -``` {.cpp} -TGeoElementTable *table = gGeoManager->GetElementTable(); -TGeoElement *element1 = table->GetElement(Int_t Z); -TGeoElement *element2 = table->FindElement("Copper"); -``` - -Materials made of single elements can be defined by their atomic mass -(`A`), charge (`Z`) and density (`rh`o). One can also create a material -by specifying the element that it is made of. Optionally the radiation -and absorption lengths can be also provided; otherwise they can be -computed on-demand [`G3`]. The class representing them is -**`TGeoMaterial`**: - -``` {.cpp} -TGeoMaterial(const char *name,Double_t a,Double_t z, - Double_t density, Double_t radlen=0,Double_t intlen=0); -TGeoMaterial(const char *name, TGeoElement *elem, - Double_t density); -TGeoMaterial(const char* name, Double_t a, Double_t z, - Double_t rho, - TGeoMaterial::EGeoMaterialState state, - Double_t temperature = STP_temperature, - Double_t pressure = STP_pressure) -``` - -Any material or derived class is automatically indexed after creation. -The assigned index is corresponding to the last entry in the list of -materials owned by **`TGeoManager`** class. This can be changed using -the **`TGeoMaterial`**`::SetIndex()` method, however it is not -recommended while using the geometry package interfaced with a transport -MC. Radiation and absorption lengths can be set using: - -``` {.cpp} -TGeoMaterial::SetRadLen(Double_t radlen, Double_t intlen); -``` - -- `radlen:` radiation length. If `radlen<=0` the value is computed - using GSMATE algorithm in GEANT3 -- `intlen:` absorption length - -Material state, temperature and pressure can be changed via setters. -Another material property is transparency. It can be defined and used -while viewing the geometry with OpenGL. - -``` {.cpp} -void SetTransparency (Char_t transparency = 0) -``` - -- `transparency:` between 0 (opaque default) to 100 (fully - transparent) - -One can attach to a material a user-defined object storing Cerenkov -properties. Another hook for material shading properties is currently -not in use. Mixtures are materials made of several elements. They are -represented by the class **`TGeoMixture`**, deriving from -**`TGeoMaterial`** and defined by their number of components and the -density: - -``` {.cpp} -TGeoMixture(const char *name,Int_t nel,Double_t rho); -``` - -Elements have to be further defined one by one: - -``` {.cpp} -void TGeoMixture::DefineElement(Int_t iel,Double_t a,Double_t z, - Double_t weigth); -void TGeoMixture::DefineElement(Int_t iel, TGeoElement *elem, - Double_t weight); -void TGeoMixture::DefineElement(Int_t iel, Int_t z, Int_t natoms); -``` - -or: - -``` {.cpp} -void AddElement(TGeoMaterial* mat, Double_t weight); -void AddElement(TGeoElement* elem, Double_t weight); -void AddElement(TGeoElement* elem, Int_t natoms); -void AddElement(Double_t a, Double_t z, Double_t weight) -``` - -- `iel:` index of the element` [0,nel-1]` -- `a` and `z:` the atomic mass and charge -- `weight:` proportion by mass of the elements -- `natoms`: number of atoms of the element in the molecule making the - mixture - -The radiation length is automatically computed when all elements are -defined. Since tracking MC provide several other ways to create -materials/mixtures, the materials classes are likely to evolve as the -interfaces to these engines are being developed. Generally in the -process of tracking material properties are not enough and more specific -media properties have to be defined. These highly depend on the MC -performing tracking and sometimes allow the definition of different -media properties (e.g. energy or range cuts) for the same material. - -### Radionuclides - -A new class **`TGeoElementRN`** was introduced in this version to -provide support for radioactive nuclides and their decays. A database of -3162 radionuclides can be loaded on demand via the table of elements -(**`TGeoElementTable`** class). One can make then materials/mixtures -based on these radionuclides and use them in a geometry - -``` {.cpp} -root[] TGeoManager *geom = new TGeoManager("geom","radionuclides"); -root[] TGeoElementTable *table = geom->GetElementTable(); -root[] TGeoElementRN *c14 = table->GetElementRN(14,6); // A,Z -root[] c14->Print(); -6-C-014 ENDF=60140; A=14; Z=6; Iso=0; Level=0[MeV]; Dmass=3.0199[MeV]; -Hlife=1.81e+11[s] J/P=0+; Abund=0; Htox=5.8e-10; Itox=5.8e-10; Stat=0 -Decay modes: -BetaMinus Diso: 0 BR: 100.000% Qval: 0.1565 -``` - -One can make materials or mixtures from radionuclides: - -``` {.cpp} -root[] TGeoMaterial *mat = new TGeoMaterial("C14", c14, 2.0); -``` - -The following properties of radionuclides can be currently accessed via -getters in the **`TGeoElementRN`** class: - -Atomic number and charge (from the base class **`TGeoElement`**) - -- Isomeric number (`ISO`) -- ENDF code - following the convention: `ENDF=10000*Z+100*A+ISO` -- Isomeric energy level [`MeV`] -- Mass excess [`MeV`] -- Half life [`s`] -- Spin/Parity - can be retrieved with: `TGeoElementRN::GetTitle()` -- Hynalation and ingestion toxicities -- List of decays - `TGeoElementRN::GetDecays()` - -The radioactive decays of a radionuclide are represented by the class -**`TGeoDecayChannel`** and they are stored in a **`TObjArray`**. Decay -provides: - -- Decay mode -- Variation of isomeric number -- `Q` value for the decay [`GeV`] -- Parent element -- Daughter element - -Radionuclides are linked one to each other via their decays, until the -last element in the decay chain which must be stable. One can iterate -decay chains using the iterator **`TGeoElemIter`**: - -``` {.cpp} -root[] TGeoElemIter next(c14); -root[] TGeoElementRN *elem; -root[] while ((elem=next())) next.Print(); -6-C-014 (100% BetaMinus) T1/2=1.81e+11 -7-N-014 stable -``` - -To create a radioactive material based on a radionuclide, one should -use the constructor: - -``` {.cpp} -TGeoMaterial(const char *name, TGeoElement *elem, Double_t density) -``` - -To create a radioactive mixture, one can use radionuclides as well as -stable elements: - -``` {.cpp} -TGeoMixture(const char *name, Int_t nelements, Double_t density); -TGeoMixture::AddElement(TGeoElement *elem, - Double_t weight_fraction); -``` - -Once defined, one can retrieve the time evolution for the radioactive -materials/mixtures by using one of the next two methods: - -1. `TGeoMaterial::FillMaterialEvolution(TObjArray *population,` -` Double_t precision=0.001)` - -To use this method, one has to provide an empty **`TObjArray`** object -that will be filled with all elements coming from the decay chain of the -initial radionuclides contained by the material/mixture. The precision -represent the cumulative branching ratio for which decay products are -still considered. - -![Concentration of C14 derived elements](pictures/030001B3.png) - -The population list may contain stable elements as well as -radionuclides, depending on the initial elements. To test if an element -is a radionuclide: - -``` {.cpp} -Bool_t TGeoElement::IsRadioNuclide() const -``` - -All radionuclides in the output population list have attached objects -that represent the time evolution of their fraction of nuclei with -respect to the top radionuclide in the decay chain. These objects -(Bateman solutions) can be retrieved and drawn: - -``` {.cpp} -TGeoBatemanSol *TGeoElementRN::Ratio(); -void TGeoBatemanSol::Draw(); -``` - -Another method allows to create the evolution of a given radioactive -material/mixture at a given moment in time: - -2. `TGeoMaterial::DecayMaterial(Double_t time, Double_t precision=0.001)` - -The method will create the mixture that result from the decay of a -initial material/mixture at time, while all resulting elements having a -fractional weight less than precision are excluded. - -A demo macro for radioactive material features is -`$ROOTSYS/tutorials/visualisation/geom/RadioNuclides.C` It demonstrates also the decay -of a mixture made of radionuclides. - -![Concentracion of elements derived -fromCa53+Sr78](pictures/030001B4.png) - -### Tracking Media - -The class **`TGeoMedium`** describes tracking media properties. This has -a pointer to a material and the additional data members representing the -properties related to tracking. - -``` {.cpp} -TGeoMedium(const char *name,Int_t numed,TGeoMaterial *mat, - Double_t *params=0); -``` - -- `name:` name assigned to the medium -- `mat:` pointer to a material -- `params:` array of additional parameters - -Another constructor allows effectively defining tracking parameters in -GEANT3 style: - -``` {.cpp} -TGeoMedium(const char *name,Int_t numed,Int_t imat,Int_t ifield, -Double_t fieldm,Double_t tmaxfd,Double_t stemax, -Double_t deemax,Double_t epsil,Double_t stmin); -``` - -This constructor is reserved for creating tracking media from the VMC -interface [...]: - -- `numed:` user-defined medium index -- `imat:` unique ID of the material -- `others:` see G3 documentation - -Looking at our simple world example, one can see that for creating -volumes one needs to create tracking media before. The way to proceed -for those not interested in performing tracking with external MC's is to -define and use only one `dummy tracking medium` as in the example (or a -`NULL` pointer). - -### User Interface for Handling Materials and Media - -The **`TGeoManager`** class contains the API for accessing and handling -defined materials: - -``` {.cpp} -TGeoManager::GetMaterial(name); -``` - -## Shapes - -Shapes are geometrical objects that provide the basic modeling -functionality. They provide the definition of the `local` coordinate -system of the volume. Any volume must have a shape. Any shape recognized -by the modeller has to derive from the base **`TGeoShape`** class, -providing methods for: - -- Finding out if a point defined in their local frame is contained or - not by the shape; -- Computing the distance to enter/exit the shape from a local point, - given a known direction; -- Computing the maximum distance in any direction from a local point - that does NOT result in a boundary crossing of the shape (safe - distance); -- Computing the cosines of the normal vector to the crossed shape - surface, given a starting local point and an ongoing direction. - -All the features above are globally managed by the modeller in order to -provide navigation functionality. In addition to those, shapes have also -to implement additional specific abstract methods: - -- Computation of the minimal box bounding the shape, given that this - box have to be aligned with the local coordinates; -- Algorithms for dividing the shape along a given axis. - -The modeller currently provides a set of 20 basic shapes, which we will -call `primitives`. It also provides a special class allowing the -creation of shapes as a result of Boolean operations between primitives. -These are called `composite shapes` and the composition operation can be -recursive (combined composites). This allows the creation of a quite -large number of different shape topologies and combinations. You can -have a look and run the tutorial: - - -![Primitive Shapes - the general inheritance scheme](pictures/030001B5.png) - -Shapes are named objects and all primitives have constructors like: - -``` {.cpp} -TGeoXXX(const char *name, param1, param2, ...); -TGeoXXX( param1, param2, ...); -``` - -Naming shape primitive is mandatory only for the primitives used in -Boolean composites (see "Composite Shapes"). For the sake of simplicity, -we will describe only the constructors in the second form. - -### Units - -The length units used in the geometry are **arbitrary**. However, there -are certain functionalities that work with the assumption that the used -lengths are expressed in centimeters. This is the case for shape -capacity or volume weight computation. The same is valid when using the -ROOT geometry as navigator for an external transport MC package (e.g. -GEANT) via the VMC interface. - -Other units in use: All angles used for defining rotation matrices or -some shape parameters are expressed in **degrees**. Material density is -expressed in [**g/cm3**]. - -### Primitive Shapes - -#### Boxes - TGeoBBox Class - -Normally a box has to be built only with 3 parameters: `DX,DY,DZ` -representing the half-lengths on X, Y and Z-axes. In this case, the -origin of the box will match the one of its reference frame and the box -will range from: `-DX` to `DX` on X-axis, from `-DY` to `DY` on Y and -from `-DZ` to `DZ` on Z. On the other hand, any other shape needs to -compute and store the parameters of their minimal bounding box. The -bounding boxes are essential to optimize navigation algorithms. -Therefore all other primitives derive from **`TGeoBBox`**. Since the -minimal bounding box is not necessary centered in the origin, any box -allows an origin translation `(Ox`,`Oy`,`Oz)`. All primitive -constructors automatically compute the bounding box parameters. Users -should be aware that building a translated box that will represent a -primitive shape by itself would affect any further positioning of other -shapes inside. Therefore it is highly recommendable to build -non-translated boxes as primitives and translate/rotate their -corresponding volumes only during positioning stage. - -``` {.cpp} -TGeoBBox(Double_t dx,Double_t dy,Double_t dz,Double_t *origin=0); -``` - -![TGeoBBox class](pictures/060001B6.png) - -#### Parallelepiped - TGeoPara class - -A parallelepiped is a shape having 3 pairs of parallel faces out of -which one is parallel with the XY plane (Z faces). All faces are -parallelograms in the general case. The Z faces have 2 edges parallel -with the X-axis. - -![TGeoPara class](pictures/060001B7.png) - -The shape has the center in the origin and it is defined by: - -- `dX, dY, dZ:` half-lengths of the projections of the edges on X, Y - and Z. The lower Z face is positioned at `-dZ`, while the upper at - `+dZ`. -- `alpha:` angle between the segment defined by the centers of the - X-parallel edges and Y axis `[-90,90]` in degrees -- `theta:` theta angle of the segment defined by the centers of the Z - faces; -- `phi:` phi angle of the same segment - -``` {.cpp} -TGeoPara(dX,dY,dZ,alpha,theta,phi); -``` - -A box is a particular parallelepiped having the parameters: -`(dX,dY,dZ,0.,0.,0.)`. - -#### Trapezoids - -In general, we will call trapezoidal shapes having 8 vertices and up to -6 trapezoid faces. Besides that, two of the opposite faces are parallel -to XY plane and are positioned at ` dZ`. Since general trapezoids are -seldom used in detector geometry descriptions, there are several -primitives implemented in the modeller for particular cases. - -`Trd1` is a trapezoid with only X varying with Z. It is defined by the -half-length in Z, the half-length in X at the lowest and highest Z -planes and the half-length in Y: - -``` {.cpp} -TGeoTrd1(Double_t dx1,Double_t dx2,Double_t dy,Double_t dz); -``` - -![TGeoTrd1 class](pictures/060001B8.png) - -`Trd2` is a trapezoid with both X and Y varying with Z. It is defined by -the half-length in Z, the half-length in X at the lowest and highest Z -planes and the half-length in Y at these planes: - -``` {.cpp} -TGeoTrd2(Double_t dx1,Double_t dx2,Double_t dy1,Double_t dy2, Double_t dz); -``` - -![TGeoTrd2 class](pictures/060001B9.png) - -#### General Trapezoid - TGeoTrap Class - -A general trapezoid is one for which the faces perpendicular to z are -trapezes but their centers are not necessary at the same x, y -coordinates. - -![TGeoTrap Class](pictures/image443.jpg) - -It has eleven parameters: the half length in z, the polar angles from -the center of the face at low z to that at high z, `H1` the half length -in y at low z, `LB1` the half length in x at low z and y low edge, `LB2` -the half length in x at low z and y high edge, **`TH1`** the angle with -respect to the y axis from the center of low y edge to the center of the -high y edge, and `H2,LB2,LH2,TH2`, the corresponding quantities at high -z. - -``` {.cpp} -TGeoTrap(Double_t dz,Double_t theta,Double_t phi, -Double_t h1,Double_t bl1,Double_t tl1,Double_t alpha1, -Double_t h2,Double_t bl2,Double_t tl2,Double_t alpha2); -``` - -#### Twisted Trapezoid - TGeoGtra class - -A twisted trapezoid is a general trapezoid defined in the same way but -that is twisted along the Z-axis. The twist is defined as the rotation -angle between the lower and the higher Z faces. - -``` {.cpp} -TGeoGtra(Double_t dz,Double_t theta,Double_t phi,Double_t twist, -Double_t h1,Double_t bl1,Double_t tl1,Double_t alpha1, -Double_t h2,Double_t bl2,Double_t tl2,Double_t alpha2 ); -``` - -![TGeoGtra class](pictures/060001BB.png) - -#### Arbitrary 8 vertices shapes - TGeoArb8 class - -An `Arb8` is defined by two quadrilaterals sitting on parallel planes, -at `dZ`. These are defined each by 4 vertices having the coordinates -`(Xi,Yi,+/-dZ)`,` i=0`,` 3`. The lateral surface of the `Arb8` is -defined by the 4 pairs of edges corresponding to vertices (`i,i+1`) on -both `-dZ` and `+dZ`. If M and M' are the middles of the segments -`(i,i+1)` at `-dZ` and `+dZ`, a lateral surface is obtained by sweeping -the edge at `-dZ` along MM' so that it will match the corresponding one -at `+dZ`. Since the points defining the edges are arbitrary, the lateral -surfaces are not necessary planes - but twisted planes having a twist -angle linear-dependent on Z. - -``` {.cpp} -TGeoArb8::TGeoArb8(Double_t dz,Double_t ivert); -``` - -- `dz:` half-length in Z; -- `ivert = [0,7]` - -Vertices have to be defined clockwise in the XY pane, both at `+dz` and -`-dz`. The quadrilateral at `-dz` is defined by indices [0,3], whereas -the one at `+dz` by vertices [4,7]. The vertex with `index=7` has to be -defined last, since it triggers the computation of the bounding box of -the shape. Any two or more vertices in each Z plane can have the same -(X,Y) coordinates. It this case, the top and bottom quadrilaterals -become triangles, segments or points. The lateral surfaces are not -necessary defined by a pair of segments, but by pair segment-point -(making a triangle) or point-point (making a line). Any choice is valid -as long as at one of the end-caps is at least a triangle. - -![TGeoArb8 class](pictures/080001BC.png) - -#### Tubes - TGeoTube Class - -Tubes have Z as their symmetry axis. They have a range in Z, a minimum -and a maximum radius: - -``` {.cpp} -TGeoTube(Double_t rmin,Double_t rmax,Double_t dz); -``` - -The full Z range is from `-dz` to `+dz`. - -![TGeoTube Class](pictures/060001BD.png) - -#### Tube Segments - TGeoTubeSeg Class - -A tube segment is a tube having a range in phi. The tube segment class -derives from **`TGeoTube`**, having 2 extra parameters: `phi1` and -`phi2`. - -``` {.cpp} -TGeoTubeSeg(Double_t rmin,Double_t rmax,Double_t dz, -Double_t phi1,Double_t phi2); -``` - -Here `phi1` and `phi2 `are the starting and ending `phi `values in -degrees. The `general phi convention` is that the shape ranges from -`phi1` to `phi2` going counterclockwise. The angles can be defined with -either negative or positive values. They are stored such that `phi1` is -converted to `[0,360]` and `phi2 > phi1`. - -![TGeoTubeSeg Class](pictures/060001BE.png) - -#### Cut Tubes - TGeoCtub Class - -The cut tubes constructor has the form: - -``` {.cpp} -TGeoCtub(Double_t rmin,Double_t rmax,Double_t dz, -Double_t phi1,Double_t phi2, -Double_t nxlow,Double_t nylow,Double_t nzlow, Double_t nxhi, -Double_t nyhi,Double_t nzhi); -``` - -![TGeoCtub Class](pictures/060001BF.png) - -A cut tube is a tube segment cut with two planes. The centers of the 2 -sections are positioned at `dZ`. Each cut plane is therefore defined by -a point `(0,0,dZ)` and its normal unit vector pointing outside the -shape: - -`Nlow=(Nx,Ny,Nz<0)`, `Nhigh=(Nx',Ny',Nz'>0)`. - -#### Elliptical Tubes - TGeoEltu Class - -An elliptical tube is defined by the two semi-axes A and B. It ranges -from `-dZ` to `+dZ` as all other tubes: - -``` {.cpp} -TGeoEltu(Double_t a,Double_t b,Double_t dz); -``` - -![TGeoEltu Class](pictures/060001C0.png) - -#### Hyperboloids - TGeoHype Class - -A hyperboloid is represented as a solid limited by two planes -perpendicular to the Z axis (top and bottom planes) and two hyperbolic -surfaces of revolution about Z axis (inner and outer surfaces). The -class describing hyperboloids is **`TGeoHype`** has 5 input parameters: - -``` {.cpp} -TGeoHype(Double_t rin,Double_t stin,Double_t rout, -Double_t stout,Double_t dz); -``` - -![TGeoHype Class](pictures/080001C1.png) - -The hyperbolic surface equation is taken in the form: - -``` {.cpp} -r2 - z2tan2() = r2min -``` - -- `r,z:` cylindrical coordinates for a point on the surface -- `:` stereo angle between the hyperbola asymptotic lines and Z axis -- `r2min:` minimum distance between hyperbola and Z axis (at `z=0`) - -The input parameters represent: - -- `rin, stin:` minimum radius and tangent of stereo angle for inner - surface -- `rout, stout:` minimum radius and tangent of stereo angle for outer - surface -- `dz:` half length in Z (bounding planes positions at `+/-dz`) - -The following conditions are mandatory in order to avoid intersections -between the inner and outer hyperbolic surfaces in the range `+/-dz`: - -- `rin0` -- `rin2 + dz2*stin2 > rout2 + dz2*stout2` - -Particular cases: - -- `rin=0, stin0:` the inner surface is conical -- `stin=0 / stout=0:` cylindrical surface(s) - -#### Cones - TGeoCone Class - -The cones are defined by 5 parameters: - -``` {.cpp} -TGeoCone(Double_t dz,Double_t rmin1,Double_t rmax1, -Double_t rmin2,Double_t rmax2); -``` - -- `rmin1:` internal radius at Z is `-dz` -- `rmax1:` external radius at Z is `-dz` -- `rmin2:` internal radius at Z is `+dz` -- `rmax2:` external radius at Z is `+dz` -- `dz:` half length in Z (a cone ranges from `-dz` to +`dz`) - -A cone has Z-axis as its symmetry axis. - -![TGeoCone Class](pictures/060001C2.png) - -#### Cone Segments - TGeoConeSeg Class - -A cone segment is a cone having a range in `phi.` The cone segment class -derives from **`TGeoCone`**, having two extra parameters: `phi1` and -`phi2`. - -``` {.cpp} -TGeoConeSeg(Double_t dz,Double_t rmin1,Double_t rmax1, -Double_t rmin2,Double_t rmax2,Double_t phi1,Double_t phi2); -``` - -Parameters` phi1` and `phi2` have the same meaning and convention as for -tube segments. - -![TGeoConeSeg Class](pictures/060001C3.png) - -#### Sphere - TGeoSphere Class - -Spheres in **`TGeo`** are not just balls having internal and external -radii, but sectors of a sphere having defined theta and phi ranges. The -**`TGeoSphere`** class has the following constructor. - -![TGeoSphere Class](pictures/060001C4.png) - -``` {.cpp} -TGeoSphere(Double_t rmin,Double_t rmax,Double_t theta1, -Double_t theta2,Double_t phi1, Double_t phi2); -``` - -- `rmin: ` internal radius of the spherical sector -- `rmax:` external radius -- `theta1:` starting theta value [0, 180) in degrees -- `theta2:` ending theta value (0, 180] in degrees (`theta1SetName("mat1"); -mat->RegisterYourself(); // see Geometrical transformations -``` - -An identifier `shape:matrix` have the meaning: `shape` is translated or -rotated with `matrix` with respect to the Boolean combination it enters -as operand. Note that in the expression A+B+C no matrix identifier was -provided, therefore the identity matrix was used for positioning the -shape components. The next example will illustrate a more complex case. - -2. `(A:m1+B):m2-(C:m3*D:m4):m5` - -Let's try to understand the expression above. This expression means: -subtract the intersection of **C** and **D** from the union of **A** and -**B**. The usage of parenthesis to force the desired precedence is -always recommended. One can see that not only the primitive shapes have -some geometrical transformations, but also their intermediate -compositions. - -![Internal representation for composite shapes](pictures/080001CC.png) - -``` {.cpp} -TGeoCompositeShape *cs2 = new TGeoCompositeShape("CS2", -"(A:m1+B):m2-(C:m3*D:m4):m5"); -``` - -Building composite shapes as in the first example is not always quite -useful since we were using un-positioned shapes. When supplying just -shape names as identifiers, the created Boolean nodes will assume that -the shapes are positioned with an identity transformation with respect -to the frame of the created composite. In order to provide some -positioning of the combination components, we have to attach after each -shape identifier the name of an existing transformation, separated by a -colon. Obviously all transformations created for this purpose have to be -objects with unique names in order to be properly substituted during -parsing. - -#### Composite Shape Example - -One should have in mind that the same shape or matrix identifiers can be -used many times in the same expression, as in the following example: - -``` {.cpp} -const Double_t sq2 = TMath::Sqrt(2.); -gSystem->Load("libGeom"); -TGeoManager *mgr = - new TGeoManager("Geom","composite shape example"); -TGeoMedium *medium = 0; -TGeoVolume *top = mgr->MakeBox("TOP",medium,100,250,250); -mgr->SetTopVolume(top); - -// make shape components -TGeoBBox *sbox = new TGeoBBox("B",100,125*sq2,125*sq2); -TGeoTube *stub = new TGeoTube("T",0,100,250); -TGeoPgon *spgon = new TGeoPgon("P",0.,360.,6,2); -spgon->DefineSection(0,-250,0,80); -spgon->DefineSection(1,250,0,80); - -// define some rotations -TGeoRotation *r1 = new TGeoRotation("r1",90,0,0,180,90,90); -r1->RegisterYourself(); -TGeoRotation *r2 = new TGeoRotation("r2",90,0,45,90,45,270); -r2->RegisterYourself(); -// create a composite -TGeoCompositeShape *cs = new TGeoCompositeShape("cs", -"((T+T:r1)-(P+P:r1))*B:r2"); -TGeoVolume *comp = new TGeoVolume("COMP",cs); -comp->SetLineColor(5); - -// put it in the top volume -top->AddNode(comp,1); -mgr->CloseGeometry(); -// visualize it with ray tracing -top->Raytrace(); -``` - -![A composite shape example](pictures/080001CD.png) - -Composite shapes can be subsequently used for defining volumes. -Moreover, these volumes contain other volumes, following the general -criteria. Volumes created based on composite shapes cannot be divided. - -### Navigation Methods Performed By Shapes - -Shapes are named objects and register themselves to the `manager class` -at creation time. This is responsible for their final deletion. Shapes -can be created without name if their retrieval by name is no needed. -Generally shapes are objects that are useful only at geometry creation -stage. The pointer to a shape is in fact needed only when referring to a -given volume and it is always accessible at that level. Several volumes -may reference a single shape; therefore its deletion is not possible -once volumes were defined based on it. - -The navigation features related for instance to tracking particles are -performed in the following way: Each shape implement its specific -algorithms for all required tasks in its local reference system. Note -that the manager class handles global queries related to geometry. -However, shape-related queries might be sometimes useful: - -``` {.cpp} -Bool_t TGeoShape::Contains(Double_t *point[3]); -``` - -The method above returns `kTRUE` if the point \*point is actually inside -the shape. The point has to be defined in the local shape reference. For -instance, for a box having `DX,DY` and `DZ `half-lengths a point will be -considered inside if: - -`-DX <= point[0] <= DX` - -`-DY <= point[1] <= DY` - -`-DZ <= point[2] <= DZ` - -``` {.cpp} -Double_t TGeoShape::DistFromInside(Double_t *point[3], -Double_t *dir[3], Int_t iact,Double_t step,Double_t *safe); -``` - -The method computes the distance to exiting a shape from a given point -`inside`, along a given direction. This direction is given by its -director cosines with respect to the local shape coordinate system. This -method provides additional information according the value of `iact` -input parameter: - -- `iact = 0`computes only safe distance and fill it at the location - given by SAFE; -- `iact = 1`a proposed STEP is supplied. The safe distance is computed - first. If this is bigger than STEP than the proposed step is - approved and returned by the method since it does not cross the - shape boundaries. Otherwise, the distance to exiting the shape is - computed and returned; -- `iact = 2`computes both safe distance and distance to exiting, - ignoring the proposed step; -- `iact > 2`computes only the distance to exiting, ignoring anything - else - -``` {.cpp} -Double_t TGeoShape::DistFromOutside(Double_t *point[3], -Double_t *dir[3],Int_t iact,Double_t step,Double_t *safe); -``` - -This method computes the distance to entering a shape from a given point -`outside`. It acts in the same way as the previous method. - -``` {.cpp} -Double_t TGeoShape::Safety(Double_t *point[3],Bool_t inside); -``` - -This computes the maximum shift of a point in any direction that does -not change its `inside/outside `state (does not cross shape boundaries). -The state of the point has to be properly supplied. - -``` {.cpp} -Double_t *TGeoShape::ComputeNormal(Double_t *point[3], -Double_t *dir[3],Double_t *norm[3]); -``` - -The method above computes the director cosines of normal to the crossed -shape surface from a given point towards direction. This is filled into -the `norm` array, supplied by the user. The normal vector is always -chosen such that its dot product with the direction is positive defined. - -### Creating Shapes - -Shape objects embeds only the minimum set of parameters that are fully -describing a valid physical shape. For instance, the half-length, the -minimum and maximum radius represent a tube. Shapes are used together -with media in order to create volumes, which in their turn are the main -components of the geometrical tree. A specific shape can be created -stand-alone: - -``` {.cpp} -TGeoBBox *box = new TGeoBBox("s_box",halfX,halfY,halfZ); // named -TGeoTube *tub = new TGeoTube(rmin,rmax,halfZ); // no name -//... (See all specific shape constructors) -``` - -Sometimes it is much easier to create a volume having a given shape in -one step, since shapes are not directly linked in the geometrical tree -but volumes are: - -``` {.cpp} -TGeoVolume *vol_box = gGeoManager->MakeBox("BOX_VOL",pmed,halfX, -halfY,halfZ); -TGeoVolume *vol_tub = gGeoManager->MakeTube("TUB_VOL",pmed,rmin, -rmax,halfZ); -// ...(See MakeXXX() utilities in TGeoManager class) -``` - -### Dividing Shapes - -Shapes can generally be divided along a given axis. Supported axes are: -`X`, `Y`, `Z`, `Rxy`, `Phi`, `Rxyz`. A given shape cannot be divided -however on any axis. The general rule is that that divisions are -possible on whatever axis that produces still known shapes as slices. -The division of shapes are performed by the call `TGeoShape::Divide()`, -but this operation can be done only via `TGeoVolume::Divide()` method. -In other words, the algorithm for dividing a specific shape is known by -the shape object, but is always invoked in a generic way from the volume -level. Details on how to do that can be found in the paragraph ‘Dividing -volumes'. One can see how all division options are interpreted and which -their result inside specific shape classes is. - -### Parametric Shapes - -Shapes generally have a set of parameters that is well defined at build -time. In fact, when the final geometrical hierarchy is assembled and the -geometry is closed, all constituent shapes `MUST`**have well defined and -valid parameters. In order to ease-up geometry creation, some -parameterizations are however allowed. - -For instance let's suppose that we need to define several volumes having -exactly the same properties but different sizes. A way to do this would -be to create as many different volumes and shapes. The modeller allows -however the definition of a single volume having undefined shape -parameters. - -``` {.cpp} -TGeoManager::Volume(const char *name,const char *shape,Int_t nmed); -``` - -- `name:` the name of the newly created volume; -- `shape:`the type of the associated shape. This has to contain the - case-insensitive first 4 letters of the corresponding class name - (e.g. "`tubs`" will match **`TGeoTubeSeg`**, "`bbox`" will match - **`TGeoBBox`**) -- `nmed:` the medium number. - -This will create a special volume that will not be directly used in the -geometry, but whenever positioned will require a list of actual -parameters for the current shape that will be created in this process. -Such volumes having shape parameters known only when used have to be -positioned only with **`TGeoManager::Node()` method (see ‘Creating and -Positioning Volumes').** - -Other case when shape parameterizations are quite useful is scaling -geometry structures. Imagine that we would like to enlarge/shrink a -detector structure on one or more axes. This happens quite often in real -life and is handled by "fitting mother" parameters. This is accomplished -by defining shapes with one or more invalid (negative) parameters. For -instance, defining a box having `dx=10.`, `dy=10.`, and `dz=-1` will not -generate an error but will be interpreted in a different way: A special -volume **`TGeoVolumeMulti`** will be created. Whenever positioned inside -a mother volume, this will create a normal **`TGeoVolume`** object -having as shape a box with `dz` fitting the corresponding `dz `of the -mother shape. Generally, this type of parameterization is used when -positioning volumes in containers having a matching shape, but it works -also for most reasonable combinations. - -## Geometry Creation - -A given geometry can be built in various ways, but one has to follow -some mandatory steps. Even if we might use some terms that will be -explained later, here are few general rules: - -- Volumes need media and shapes in order to be created. -- Both containers and contained volumes must be created before linking - them together, and the relative transformation matrix must be - provided. -- Any volume have to be positioned somewhere otherwise it will not be - considered as part of the geometry. -- Visibility or tracking properties of volumes can be provided both at - build time or after geometry is closed, but global visualization - settings (see section: "The Drawing Package") should not be provided - at build time, otherwise the drawing package will be loaded. - -There is also a list of specific rules: - -- Positioned volumes should not extrude their container or intersect - with others within this unless it is specified (see section: - Overlapping Volumes). -- The top volume (containing all geometry trees) must be specified - before closing the geometry and must not be positioned - it - represents the global reference frame. -- After building the full geometry tree, the geometry must be closed - (see the method **`TGeoManager`**`::CloseGeometry()`). Voxelization - can be redone per volume after this process. - -The list is much bigger and we will describe in more detail the geometry -creation procedure in the following sections. Provided that geometry was -successfully built and closed, the **`TGeoManager`** class will register -itself to ROOT and the logical/physical structures will become -immediately browsable. - -### The Volume Hierarchy - -The basic components used for building the logical hierarchy of the -geometry are the positioned volumes called `nodes`. Volumes are fully -defined geometrical objects having a given shape and medium and possibly -containing a list of nodes. Nodes represent just positioned instances of -volumes inside a container volume but users do not directly create them. -They are automatically created as a result of adding one volume inside -other or dividing a volume. The geometrical transformation held by nodes -is always defined with respect to their mother (relative positioning). -Reflection matrices are allowed. - -A hierarchical element is not fully defined by a node since nodes are -not directly linked to each other, but through volumes (a node points to -a volume, which at its turn points to a list of nodes): - -`NodeTop ` ` VolTop ` ` NodeA ` ` VolA ` `...` - -One can therefore talk about "the node or volume hierarchy", but in -fact, an element is made by a pair volume-node. In the line above is -represented just a single branch, but of course from any volume other -branches can also emerge. The index of a node in such a branch (counting -only nodes) is called `depth`. The top node have always `depth=0`. - -Volumes need to have their daughter nodes defined when the geometry is -closed. They will build additional structures (called `voxels` ) in -order to fasten-up the search algorithms. Finally, nodes can be regarded -as bi-directional links between containers and contained volumes. - -The structure defined in this way is a graph structure since volumes are -replicable (same volume can become daughter node of several other -volumes), every volume becoming a branch in this graph. Any volume in -the logical graph can become the actual top volume at run time (see -**`TGeoManager::SetTopVolume()`). All functionalities of the modeller -will behave in this case as if only the corresponding branch starting -from this volume is the active geometry.** - -![A geometry hierarchy in memory](pictures/030001CE.png) - -Nodes are never instantiated directly by users, but created as a result -of volume operations. Adding a volume named A with a given `user id` -inside a volume B will create a node named `A_id.` This will be added to -the list of nodes stored by B. In addition, when applying a division -operation in N slices to a volume A, a list of nodes `B_1`, `B_2`, ... , -`B_N` is also created. A node `B_i` does not represent a unique object -in the geometry because its container A might be at its turn positioned -as node inside several other volumes. Only when a complete branch of -nodes is fully defined up to the top node in the geometry, a given -path:` /TOP_1/`...`/A_3/B_7` will represent a unique object. Its global -transformation matrix can be computed as the pile-up of all local -transformations in its branch. We will therefore call `logical graph` -the hierarchy defined by nodes and volumes. The expansion of the logical -graph by all possible paths defines a tree structure where all nodes are -unique "touchable" objects. We will call this the "physical tree". -Unlike the logical graph, the physical tree can become a huge structure -with several millions of nodes in case of complex geometries; therefore, -it is not always a good idea to keep it transient in memory. Since the -logical and physical structures are correlated, the modeller rather -keeps track only of the current branch, updating the current global -matrix at each change of the level in geometry. The current physical -node is not an object that can be asked for at a given moment, but -rather represented by the combination: current node/current global -matrix. However, physical nodes have unique ID's that can be retrieved -for a given modeller state. These can be fed back to the modeller in -order to force a physical node to become current. The advantage of this -comes from the fact that all navigation queries check first the current -node; therefore the location of a point in the geometry can be saved as -a starting state for later use. - -Nodes can be declared as `overlapping` in case they do overlap with -other nodes inside the same container or extrude this container (see -also ‘Checking the Geometry'). Non-overlapping nodes can be created -with: - -``` {.cpp} -TGeoVolume::AddNode(TGeoVolume *daughter,Int_t copy_No, -TGeoMatrix *matr); -``` - -The creation of overlapping nodes can be done with a similar prototype: - -``` {.cpp} -TGeoVolume::AddNodeOverlap(/*same arguments*/); -``` - -When closing the geometry, overlapping nodes perform a check of possible -overlaps with their neighbors. These are stored and checked all the time -during navigation; therefore, navigation is slower when embedding such -nodes into geometry. Nodes have visualization attributes as the volume -has. When undefined by users, painting a node on a pad will take the -corresponding volume attributes. - -### Creating and Positioning Volumes - -#### Making Volumes - -As mentioned before, volumes are the basic objects used in building the -geometrical hierarchy. They represent objects that are not positioned, -but store all information about the placement of the other volumes they -may contain. Therefore a volume can be replicated several times in the -geometry. As it was explained, in order to create a volume, one has to -put together a shape and a medium, which are already defined. - -Volumes have to be named by users at creation time. Every different name -may represent a unique volume object, but may also represent more -general a family (class) of volume objects having the same shape type -and medium, but possibly different shape parameters. It is the user's -task to provide different names for different volume families in order -to avoid ambiguities at tracking time. - -A generic family rather than a single volume is created only in two -cases: when a parametric shape is used or when a division operation is -applied. Each volume in the geometry stores a unique ID corresponding to -its family. In order to ease-up their creation, the manager class is -providing an API that allows making a shape and a volume in a single -step. - -#### Example of Volume Creation - -``` {.cpp} -// Making a volume out of a shape and a medium. -TGeoVolume *vol = new TGeoVolume("VNAME",ptrShape,ptrMed); - -// Making a volume out of a shape but without a defined medium. -TGeoVolume *vol = new TGeoVolume("VNAME",ptrShape); - -// Making a volume with a given shape in one step -TGeoVolume *vol = gGeoManager->MakeBox("VNAME",ptrMed,dx,dy,dz); -TGeoVolume *vol = gGeoManager->MakeTubs("VNAME",ptrMed,rmin,rmax, -dz,phi1,phi2); - -// See class TGeoManager for the rest of shapes. -// Making a volume with a given shape with a unique prototype -TGeoVolume *vol = gGeoManager->Volume("VNAME","XXXX",nmed,upar, -npar); - -// Where XXXX stands for the first 4 letters of the specific shape -// classes, nmed is the medium number, upar is an Double_t * array -// of the shape parameters and npar is the number of parameters. -// This prototype allows (npar = 0) to define volumes with shape -// defined only at positioning time (volumes defined in this way -// need to be positioned using TGeoManager::Node() method) -``` - -#### Positioned Volumes (Nodes) - -Geometrical modeling is a difficult task when the number of different -geometrical objects is 106-108. This is more or less the case for -detector geometries of complex experiments, where a ‘flat' CSG model -description cannot scale with the current CPU performances. This is the -reason why models like GEANT [1] introduced an additional dimension -(depth) in order to reduce the complexity of the problem. This concept -is also preserved by the ROOT modeller and introduces a pure geometrical -constraint between objects (volumes in our case) - containment. This -means in fact that any positioned volume has to be contained by another. -Now what means contained and positioned? - -- We will say that a volume `contains` a point if this is inside the - shape associated to the volume. For instance, a volume having a box - shape will contain all points `P=(X,Y,Z)` verifying the conditions: - `Abs(Pi)dXi`. The points on the shape boundaries are considered as - inside the volume. The volume contains a daughter if it contains all - the points contained by the daughter. -- The definition of containment works of course only with points - defined in the local coordinate system of the considered volume. - `Positioning` a volume inside another have to introduce a - geometrical transformation between the two. If `M` defines this - transformation, any point in the daughter reference can be converted - to the mother reference by: `Pmother = MPdaughter` - -When creating a volume one does not specify if this will contain or not -other volumes. Adding daughters to a volume implies creating those and -adding them one by one to the list of daughters. Since the volume has to -know the position of all its daughters, we will have to supply at the -same time a geometrical transformation with respect to its local -reference frame for each of them. - -``` {.cpp} -TGeoVolume::AddNode(TGeoVolume *daughter,Int_t usernumber, -TGeoMatrix *matrix=gGeoIdentity) -``` - -The objects referencing a volume and a transformation are called `NODES` -and their creation is fully handled by the modeller. They represent the -link elements in the hierarchy of volumes. Nodes are unique and distinct -geometrical objects ONLY from their container point of view. Since -volumes can be replicated in the geometry, the same node may be found on -different branches. - -In order to provide navigation features, volumes have to be able to find -the proper container of any point defined in the local reference frame. -This can be the volume itself, one of its positioned daughter volumes or -none if the point is actually outside. On the other hand, volumes have -to provide also other navigation methods such as finding the distances -to its shape boundaries or which daughter will be crossed first. The -implementation of these features is done at shape level, but the local -mother-daughters management is handled by volumes. These build -additional optimization structures upon geometry closure. In order to -have navigation features properly working one has to follow some rules -for building a valid geometry. - -- The daughter volume(s) must not extrude the mother shape. They are - allowed however to have a common boundaries. -- The volumes positioned in the same container must not overlap with - each other. They may touch on one boundaries or shape vertex. - -The daughter nodes of a volume can be also removed or replaced with -other nodes: - -``` {.cpp} -void RemoveNode(TGeoNode* node) -TGeoNode*ReplaceNode(TGeoNode* nodeorig, TGeoShape* newshape = 0, -TGeoMatrix* newpos = 0, TGeoMedium* newmed = 0) -``` - -The last method allows replacing an existing daughter of a volume with -another one. Providing only the node to be replaced will just create a -new volume for the node but having exactly the same parameters as the -old one. This helps in case of divisions for decoupling a node from the -logical hierarchy so getting new content/properties. For non-divided -volumes, one can change the shape and/or the position of the daughter. - -#### Virtual Containers and Assemblies of Volumes - -Virtual containers are volumes that do not represent real objects, but -they are needed for grouping and positioning together other volumes. -Such grouping helps not only geometry creation, but also optimizes -tracking performance; therefore, it is highly recommended. Virtual -volumes need to inherit material/medium properties from the volume they -are placed into in order to be "invisible" at tracking time. - -Let us suppose that we need to group together two volumes `A` and `B` -into a structure and position this into several other volumes `D,E,` and -`F`. What we need to do is to create a virtual container volume `C` -holding `A` and `B`, then position `C` in the other volumes. - -Note that `C` is a volume having a determined medium. Since it is not a -real volume, we need to manually set its medium the same as that of -`D,E` or `F` in order to make it ‘invisible' (same physics properties). -In other words, the limitation in proceeding this way is that `D,E,` and -`F` must point to the same medium. If this was not the case, we would -have to define different virtual volumes for each placement: `C`, `C'` -and `C"`, having the same shape but different media matching the -corresponding containers. This might not happen so often, but when it -does, it forces the creation of several extra virtual volumes. Other -limitation comes from the fact that any container is directly used by -navigation algorithms to optimize tracking. These must geometrically -contain their belongings (positioned volumes) so that these do not -extrude its shape boundaries. Not respecting this rule generally leads -to unpredictable results. Therefore `A` and `B` together must fit into -`C` that has to fit also into `D,E,` and `F`. This is not always -straightforward to accomplish, especially when instead of `A` and `B` we -have many more volumes. - -In order to avoid these problems, one can use for the difficult cases -the class **`TGeoVolumeAssembly`**, representing an assembly of volumes. -This behaves like a normal container volume supporting other volumes -positioned inside, but it has neither shape nor medium. It cannot be -used directly as a piece of the geometry, but just as a temporary -structure helping temporary assembling and positioning volumes. - -If we define now `C` as an assembly containing `A` and `B`, positioning -the assembly into `D,E` and `F` will actually position only `A` and -`B `directly into these volumes, taking into account their combined -transformations `A/B` to `C` and `C` to `D/E/F`. This looks much nicer, -is it? In fact, it is and it is not. Of course, we managed to get rid of -the ‘unnecessary' volume `C` in our geometry, but we end-up with a more -flat structure for `D,E` and `F` (more daughters inside). This can get -much worse when extensively used, as in the case: assemblies of -assemblies. - -For deciding what to choose between using virtual containers or -assemblies for a specific case, one can use for both cases, after the -geometry was closed: - -``` {.cpp} -gGeoManager->SetTopVolume(ptr_D); -gGeoManager->Test(); -gGeoManager->RestoreMasterVolume(); -``` - -The `ptr_D` is a pointer to volume `D` containing the interesting -structure. The test will provide the timing for classifying 1 million -random points inside `D`. - -#### Examples of Volume Positioning - -Now let us make a simple volume representing a copper wire. We suppose -that a medium is already created (see **`TGeoMedium`** class on how to -create media). - -We will create a `TUBE` shape for our wire, having `Rmin=0cm`, -`Rmax=0.01cm` and a half-length `dZ=1cm`: - -``` {.cpp} -TGeoTube *tube = new TGeoTube("wire_tube",0,0.01,1); -``` - -One may omit the name for the shape `wire_tube,` if no retrieving by -name is further needed during geometry building. Different volumes -having different names and materials can share the same shape. - -Now let's make the volume for our wire: - -``` {.cpp} -TGeoVolume *wire_co = new TGeoVolume("WIRE_CO",tube, -ptrCOPPER); //(*) -``` - -**(\*)** Do not bother to delete the media, shapes or volumes that you -have created since all will be automatically cleaned on exit by the -manager class. - -If we would have taken a look inside `TGeoManager::MakeTube()` method, -we would have been able to create our wire with a single line: - -``` {.cpp} -TGeoVolume *wire_co = gGeoManager->MakeTube("WIRE_CO",ptrCOPPER, -0,0.01,1); //(*) -``` - -**(\*)** The same applies for all primitive shapes, for which there can -be found corresponding `MakeSHAPE()` methods. Their usage is much more -convenient unless a shape has to be shared between more volumes. - -Let us make now an aluminum wire having the same shape, supposing that -we have created the copper wire with the line above: - -``` {.cpp} -TGeoVolume *wire_al = new TGeoVolume("WIRE_AL",wire_co>GetShape(), -ptrAL); -``` - -We would like now to position our wire in the middle of a gas chamber. -We need first to define the gas chamber: - -``` {.cpp} -TGeoVolume *chamber = gGeoManager->MakeTube("CHAMBER",ptrGAS, -0,1,1); -``` - -Now we can put the wire inside: - -``` {.cpp} -chamber->AddNode(wire_co,1); -``` - -If we inspect now the chamber volume in a browser, we will notice that -it has one daughter. Of course, the gas has some container also, but let -us keeps it like that for the sake of simplicity. Since we did not -supply the third argument, the wire will be positioned with an identity -transformation inside the chamber. - -#### Overlapping Volumes - -Positioning volumes that does not overlap their neighbors nor extrude -their container is sometimes quite strong constraint. Having a limited -set of geometric shapes might force sometimes overlaps. Since -overlapping is contradictory to containment, a point belonging to an -overlapping region will naturally belong to all overlapping partners. -The answer provided by the modeller to "Where am I?" is no longer -deterministic if there is no priority assigned. - -There are two ways out provided by the modeller in such cases and we -will illustrate them by examples. - -- Suppose we have 2 crossing tubes that we have to describe. Such a - structure cannot be decomposed in a containment schema. This is a - typical example of simple structure that can be handled by using - composite shapes. What we have to do is to define as shapes the - inner and outer parts of the tubes (tubes having - `Rmin=0`,` Rmax=`inner/outer radius), then to make a composite: -- `C = (Tub1out+Tub2out)-(Tub1in+Tub2in)` -- On the other hand, if we have an EM calorimeter having a honeycomb - structure, Boolean combinations do not help anymore. Here the - problem is that we usually have a very large number of cells that - are naturally belonging to the same container. This result in a very - flat and slow structure for that particular container, which we - would very much want to avoid by introducing additional levels in - depth. We can describe the basic cell as a hexahedron that we can - represent by using a polygon primitive shape. Instead of putting one - by one all cells in the same container, we can define rows of such - elements, fitting in box-shaped containers. Then we can put - row-beside-row inside the container, making life much easier for its - navigation algorithms. The problem is that in order to reproduce the - honeycomb structure out of rows of cells, we have to overlap row - containers. Whoops - we have not obeyed rule No. 2 in positioning. - The way out is to position our rows with a special prototype: - -``` {.cpp} -ptrCAL->AddNodeOverlap("ROW",nRow,matrixRow); -``` - -This will instruct the modeller that the daughter ROW inside CAL -overlaps with something else. The modeller will check this at closure -time and build a list of possibly overlapping candidates. This option is -equivalent with the option MANY in GEANT3. - -The modeller supports such cases only if user declares the overlapping -nodes. In order to do that, one should use -**`TGeoVolume`**`::AddNodeOverlap()` instead of `TGeoVolume::AddNode()`. -When two or more positioned volumes are overlapping, not all of them -have to be declared so, but at least one. A point inside an overlapping -region equally belongs to all overlapping nodes, but the way these are -defined can enforce the modeller to give priorities. - -The general rule is that the deepest node in the hierarchy containing a -point has the highest priority. For the same geometry level, -non-overlapping is prioritized over overlapping. In order to illustrate -this, we will consider few examples. We will designate non-overlapping -nodes as ONLY and the others MANY as in GEANT3, where this concept was -introduced: - -1. The part of a MANY node B extruding its container A will never be -"seen" during navigation, as if B was in fact the result of the -intersection of A and B. - -2. If we have two nodes A (ONLY) and B (MANY) inside the same container, -all points in the overlapping region of A and B will be designated as -belonging to A. - -3. If A an B in the above case were both MANY, points in the overlapping -part will be designated to the one defined first. Both nodes must have -the same medium. - -4. The slices of a divided MANY will be as well MANY. - -One needs to know that navigation inside geometry parts MANY nodes is -much slower. Any overlapping part can be defined based on composite -shapes - might be in some cases a better way out. - -#### Replicating Volumes - -What can we do if our chamber contains two identical wires instead of -one? What if then we would need 1000 chambers in our detector? Should we -create 2000 wires and 1000 chamber volumes? No, we will just need to -replicate the ones that we have already created. - -``` {.cpp} -chamber->AddNode(wire_co,1,new TGeoTranslation(0.2,0,0)); -chamber->AddNode(wire_co,2,new TGeoTranslation(0.2,0,0)); -``` - -The 2 nodes that we have created inside chamber will both point to a -`wire_co` object, but will be completely distinct: `WIRE_CO_1` and -`WIRE_CO_2`. We will want now to place symmetrically 1000 chambers on a -pad, following a pattern of 20 rows and 50 columns. One way to do this -will be to replicate our chamber by positioning it 1000 times in -different positions of the pad. Unfortunately, this is far from being -the optimal way of doing what we want. Imagine that we would like to -find out which of the 1000 chambers is containing a `(x,y,z)` point -defined in the pad reference. You will never have to do that, since the -modeller will take care of it for you, but let's guess what it has to -do. The most simple algorithm will just loop over all daughters, convert -the point from mother to local reference and check if the current -chamber contains the point or not. This might be efficient for pads with -few chambers, but definitely not for 1000. Fortunately the modeller is -smarter than that and creates for each volume some optimization -structures called `voxels` to minimize the penalty having too many -daughters, but if you have 100 pads like this in your geometry you will -anyway lose a lot in your tracking performance. The way out when -volumes can be arranged according to simple patterns is the usage of -divisions. We will describe them in detail later on. Let's think now at -a different situation: instead of 1000 chambers of the same type, we may -have several types of chambers. Let's say all chambers are cylindrical -and have a wire inside, but their dimensions are different. However, we -would like all to be represented by a single volume family, since they -have the same properties. - -#### Volume Families - -A volume family is represented by the class **`TGeoVolumeMulti`**. It -represents a class of volumes having the same shape type and each member -will be identified by the same name and volume ID. Any operation applied -to a **`TGeoVolumeMulti`** equally affects all volumes in that family. -The creation of a family is generally not a user task, but can be forced -in particular cases: - -``` {.cpp} -TGeoManager::Volume(const char *vname,const char *shape, -Int_t nmed); -``` - -Where: `vname` is the family name, `nmed` is the medium number and -`shape` is the shape type that can be: - -- `box`for **`TGeoBBox`** -- `trd1`for **`TGeoTrd1`** -- `trd2`for **`TGeoTrd2`** -- `trap`for **`TGeoTrap`** -- `gtra`for **`TGeoGtra`** -- `para`for **`TGeoPara`** -- `tube`, `tubs `for **`TGeoTube`**, **`TGeoTubeSeg`** -- ` cone`, `cons `for **`TGeoCone`**, **`TGeoCons`** -- `eltu`for **`TGeoEltu`** -- `ctub`for **`TGeoCtub`** -- `pcon`for **`TGeoPcon`** -- `pgon`for **`TGeoPgon`** - -Volumes are then added to a given family upon adding the generic name as -node inside other volume: - -``` {.cpp} -TGeoVolume *box_family = gGeoManager->Volume("BOXES","box",nmed); -// ... -gGeoManager->Node("BOXES",Int_t copy_no,"mother_name",Double_t x, -Double_t y,Double_t z,Int_t rot_index,Bool_t is_only, -Double_t *upar,Int_t npar); -``` - -- `BOXES`- name of the family of boxes -- `copy_no`- user node number for the created node -- `mother_name`- name of the volume to which we want to add the node -- `x,y,z`- translation components -- `rot_index`- index of a rotation matrix in the list of matrices -- `upar`- array of actual shape parameters -- `npar`- number of parameters - -The parameters order and number are the same as in the corresponding -shape constructors. Another particular case where volume families are -used is when we want that a volume positioned inside a container to -match one ore more container limits. Suppose we want to position the -same box inside 2 different volumes and we want the Z size to match the -one of each container: - -``` {.cpp} -TGeoVolume *container1 = gGeoManager->MakeBox("C1",imed,10,10,30); -TGeoVolume *container2 = gGeoManager->MakeBox("C2",imed,10,10,20); -TGeoVolume *pvol = gGeoManager->MakeBox("PVOL",jmed,3,3,-1); -container1->AddNode(pvol,1); -container2->AddNode(pvol,1); -``` - -Note that the third parameter of `PVOL` is negative, which does not make -sense as half-length on Z. This is interpreted as: when positioned, -create a box replacing all invalid parameters with the corresponding -dimensions of the container. This is also internally handled by the -**`TGeoVolumeMulti`** class, which does not need to be instantiated by -users. - -#### Dividing Volumes - -Volumes can be divided according a pattern. The simplest division can be -done along one axis that can be: `X,Y,Z,Phi,Rxy or Rxyz`. Let's take a -simple case: we would like to divide a box in N equal slices along X -coordinate, representing a new volume family. Supposing we already have -created the initial box, this can be done like: - -``` {.cpp} -TGeoVolume *slicex = box->Divide("SLICEX",1,N); -``` - -Here `SLICEX` is the name of the new family representing all slices and -1 is the slicing axis. The meaning of the axis index is the following: -for all volumes having shapes like `box`, `trd1`, `trd2`, `trap`, -`gtra `or` para - `1, 2, 3 mean X, Y, Z; for `tube`, `tubs`, `cone`, -`cons - `1 means `Rxy`, 2 means `phi` and 3 means Z; for `pcon` and -`pgon` - 2 means `phi` and 3 means Z; for spheres 1 means `R `and 2 -means `phi.` - -In fact, the division operation has the same effect as positioning -volumes in a given order inside the divided container - the advantage -being that the navigation in such a structure is much faster. When a -volume is divided, a volume family corresponding to the slices is -created. In case all slices can be represented by a single shape, only -one volume is added to the family and positioned N times inside the -divided volume, otherwise, each slice will be represented by a distinct -volume in the family. - -Divisions can be also performed in a given range of one axis. For that, -one has to specify also the starting coordinate value and the step: - -``` {.cpp} -TGeoVolume *slicex = box->Divide("SLICEX",1,N,start,step); -``` - -A check is always done on the resulting division range: if not fitting -into the container limits, an error message is posted. If we will browse -the divided volume we will notice that it will contain N nodes starting -with index 1 up to N. The first one has the lower X limit at `START` -position, while the last one will have the upper X limit at -`START+N*STEP`. The resulting slices cannot be positioned inside another -volume (they are by default positioned inside the divided one) but can -be further divided and may contain other volumes: - -``` {.cpp} -TGeoVolume *slicey = slicex->Divide("SLICEY",2,N1); -slicey->AddNode(other_vol,index,some_matrix); -``` - -When doing that, we have to remember that `SLICEY` represents a family, -therefore all members of the family will be divided on Y and the other -volume will be added as node inside all. - -In the example above all the resulting slices had the same shape as the -divided volume (box). This is not always the case. For instance, -dividing a volume with `TUBE` shape on `PHI `axis will create equal -slices having `TUBESEG` shape. Other divisions can also create slices -having shapes with different dimensions, e.g. the division of a `TRD1` -volume on Z. - -When positioning volumes inside slices, one can do it using the generic -volume family (e.g. `slicey`). This should be done as if the coordinate -system of the generic slice was the same as the one of the divided -volume. The generic slice in case of `PHI` division is centered with -respect to X-axis. If the family contains slices of different sizes, any -volume positioned inside should fit into the smallest one. - -Examples for specific divisions according to shape types can be found -inside shape classes. - -``` {.cpp} -TGeoVolume::Divide(N,Xmin,Xmax,"X"); -``` - -Create a new volume by dividing an existing one (GEANT3 like). - -Divides `MOTHER` into `NDIV` divisions called `NAME` along axis `IAXIS` -starting at coordinate value `START` and having size `STEP`. The created -volumes will have tracking media `ID=NUMED` (if `NUMED=0` -\> same media -as `MOTHER`). - -The behavior of the division operation can be triggered using `OPTION` -(case insensitive): - -- `N`divide all range in `NDIV` cells (same effect as `STEP<=0`) - (GSDVN in G3) -- `NX`divide range starting with `START` in `NDIV` cells (GSDVN2 in - G3) -- `S`divide all range with given `STEP`; `NDIV` is computed and - divisions will be centered in full range (same effect as `NDIV<=0`) - (GSDVS, GSDVT in G3) -- `SX`same as `DVS`, but from `START` position (GSDVS2, GSDVT2 in G3) - -#### Volume Assemblies - -In general, geometry contains structures of positioned volumes that have -to be grouped and handled together, for different possible reasons. One -of these is that the structure has to be replicated in several parts of -the geometry, or it may simply happen that they really represent a -single object, too complex to be described by a primitive shape. - -Usually handling structures like these can be easily done by positioning -all components in the same container volume, then positioning the -container itself. However, there are many practical cases when defining -such a container is not straightforward or even possible without -generating overlaps with the rest of the geometry. There are few ways -out of this: - -- Defining the container for the structure as "overlapping" (see also - " Overlapping Volumes **"**) -- Representing the container as a composite shape - the Boolean union - of all components (see also " Composite Shapes ") -- Using an assembly volume - this will be described in the following. - -The first two approaches have the disadvantage of penalizing the -navigation performance with a factor increasing more than linear of the -number of components in the structure. The best solution is the third -one because it uses all volume-related navigation optimizations. The -class **`TGeoVolumeAssembly`** represents an assembly volume. Its shape -is represented by **`TGeoShapeAssembly`** class that is the union of all -components. It uses volume voxelization to perform navigation tasks. - -An assembly volume creates a hierarchical level and it geometrically -insulates the structure from the rest (as a normal volume). Physically, -a point that is INSIDE a **`TGeoShapeAssembly`** is always inside one of -the components, so a **`TGeoVolumeAssembly`** does not need to have a -medium. Due to the self-containment of assemblies, they are very -practical to use when a container is hard to define due to possible -overlaps during positioning. For instance, it is very easy creating -honeycomb structures. A very useful example for creating and using -assemblies can be found at: -`.` - -Creation of an assembly is very easy: one has just to create a -**`TGeoVolumeAssembly`** object and position the components inside as -for any volume: - -``` {.cpp} -TGeoVolume *vol = new TGeoVolumeAssembly(name); -vol->AddNode(vdaughter1, cpy1, matrix1); -vol->AddNode(vdaughter2, cpy2, matrix2); -``` - -Note that components cannot be declared as "overlapping" and that a -component can be an assembly volume. For existing flat volume -structures, one can define assemblies to force a hierarchical structure -therefore optimizing the performance. Usage of assemblies does NOT imply -penalties in performance, but in some cases, it can be observed that it -is not as performing as bounding the structure in a container volume -with a simple shape. Choosing a normal container is therefore -recommended whenever possible. - -![Assemblies of volumes](pictures/080001CF.png) - -### Geometrical Transformations - -All geometrical transformations handled by the modeller are provided as -a built-in package. This was designed to minimize memory requirements -and optimize performance of point/vector master-to-local and -local-to-master computation. We need to have in mind that a -transformation in **`TGeo`** has two major use-cases. The first one is -for defining the placement of a volume with respect to its container -reference frame. This frame will be called 'master' and the frame of the -positioned volume - 'local'. If `T` is a transformation used for -positioning volume daughters, then: `MASTER = T * LOCAL` - -Therefore `T `is used to perform a local to master conversion, while -`T-1` for a master to local conversion. The second use case is the -computation of the global transformation of a given object in the -geometry. Since the geometry is built as 'volumes-inside-volumes', the -global transformation represents the pile-up of all local -transformations in the corresponding branch. Once a given object in the -hierarchy becomes the current one, the conversion from master to local -coordinates or the other way around can be done from the manager class. - -A general homogenous transformation is defined as a 4x4 matrix embedding -a rotation, a translation and a scale. The advantage of this description -is that each basic transformation can be represented as a homogenous -matrix, composition being performed as simple matrix multiplication. - -Rotation: -$\left|\begin{array}{cccc} - r_{11} & r_{12} & r_{13} & 0 \\ - r_{21} & r_{22} & r_{23} & 0 \\ - r_{31} & r_{32} & r_{33} & 0 \\ - 0 & 0 & 0 & 1 -\end{array} -\right|$ -Translation: -$\left|\begin{array}{cccc} - 1 & 0 & 0 & 0 \\ - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - t_x & t_y & t_z & 1 -\end{array} -\right|$ -Scale: -$\left|\begin{array}{cccc} - s_x & 0 & 0 & 0 \\ - 0 & s_y & 0 & 0 \\ - 0 & 0 & s_z & 0 \\ - 0 & 0 & 0 & 1 -\end{array} -\right|$ - -Inverse rotation: -$\left|\begin{array}{cccc} - r_{11} & r_{21} & r_{31} & 0 \\ - r_{12} & r_{22} & r_{32} & 0 \\ - r_{13} & r_{23} & r_{33} & 0 \\ - 0 & 0 & 0 & 1 -\end{array} -\right|$ -Inverse translation: -$\left|\begin{array}{cccc} - 1 & 0 & 0 & 0 \\ - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - -t_x & -t_y & -t_z & 1 -\end{array} -\right|$ -Inverse scale: -$\left|\begin{array}{cccc} - \frac{1}{s_x} & 0 & 0 & 0 \\ - 0 & \frac{1}{s_y} & 0 & 0 \\ - 0 & 0 & \frac{1}{s_z} & 0 \\ - 0 & 0 & 0 & 1 -\end{array} -\right|$ - -- $r_{ij}$ are the 3x3 rotation matrix components -- $t_x$,$t_y$,$t_z$ are the translation components -- $s_x$, $s_y$, $s_z$ are arbitrary scale constants on each axis - -The disadvantage in using this approach is that computation for 4x4 -matrices is expensive. Even combining two translations would become a -multiplication of their corresponding matrices, which is quite an -undesired effect. On the other hand, it is not a good idea to store a -translation as a block of 16 numbers. We have therefore chosen to -implement each basic transformation type as a class deriving from the -same basic abstract class and handling its specific data and -point/vector transformation algorithms. - -The base class **`TGeoMatrix`** defines abstract methods for: - -- Translation, rotation and scale getters. Every derived class stores - only its specific data, e.g. a translation stores an array of 3 - doubles and a rotation an array of 9. However, getting the - **`TGeoTranslation`** rotation array through the base - **`TGeoMatrix`** interface is a legal operation. The answer in this - case is a pointer to a global constant array representing an - identity rotation. - -``` {.cpp} -Double_t *TGeoMatrix::GetTranslation() const; -Double_t *TGeoMatrix::GetRotation() const; -Double_t *TGeoMatrix::GetScale() const; -``` - -- Master-to-local and local-to-master point and vector transformations - : - -``` {.cpp} -void TGeoMatrix::MasterToLocal(const Double_t *master, -Double_t *local) -void TGeoMatrix::LocalToMaster(const Double_t *local, -Double_t *master) -void TGeoMatrix::MasterToLocalVect(const Double_t *master, -Double_t *local) -void TGeoMatrix::LocalToMasterVect(const Double_t *local, -Double_t *master) -``` - -Here `master` and `local` are arrays of size 3. These methods allow -correct conversion also for reflections. - -- Transformation type finding: - -``` {.cpp} -Bool_t TGeoMatrix::IsIdentity() const; -Bool_t TGeoMatrix::IsTranslation() const; -Bool_t TGeoMatrix::IsRotation() const; -Bool_t TGeoMatrix::IsScale() const; -Bool_t TGeoMatrix::IsCombi() const; // (tr. + rot.) -Bool_t TGeoMatrix::IsGeneral() const; // (tr. + rot. + scale) -``` - -Specific classes deriving from **`TGeoMatrix`** represent combinations -of basic transformations. In order to define a matrix as a combination -of several others, a special class **`TGeoHMatrix`** is provided. Here -is an example of matrix creation: - -#### Matrix Creation Example - -``` {.cpp} -TGeoRotation r1,r2; -r1.SetAngles(90,0,30); //rotation defined by Euler angles -r2.SetAngles(90,90,90,180,0,0); //rotation defined by GEANT3 angles -TGeoTranslation t1(-10,10,0); -TGeoTranslation t2(10,-10,5); -TGeoCombiTrans c1(t1,r1); -TGeoCombiTrans c2(t2,r2); -TGeoHMatrix h = c1 * c2; // composition is done via TGeoHMatrix -TGeoHMatrix *ph = new TGeoHMatrix(hm); // class it is what we want - // to use for positioning - // a volume -ph->Print(); -... -pVolume->AddNode(pVolDaughter,id,ph) // now ph is owned by - the manager -``` - -#### Rule for Creation of Transformations - -Unless explicitly used for positioning nodes `(TGeoVolume::AddNode())` -all matrices deletion have to be managed by users. Matrices passed to -geometry have to be created by using `new()` operator and -**`TGeoManager`** class is responsible for their deletion. Matrices that -are used for the creation of composite shapes have to be named and -registered to the manager class: - -``` {.cpp} -transf->SetName(name); // if not already named in the constructor -transf->RegisterYourself(); -``` - -Generally, it is advisable to create all intermediate transformations -used for making the final combined one on the heap: - -``` {.cpp} -TGeoRotation r1(...); -TGeoRotation r2(...); -TGeoHMatrix *mat = new TGeoHMatrix("name"); // we want to use only - // this one in geometry -*mat = r1 * r2; -``` - -#### Available Geometrical Transformations - -- Translations (**`TGeoTranslation`** class) represent a `(dx,dy,dz)` - translation. The only data member is: `Double_t fTranslation[3]`. - Translations can be added or subtracted. - -``` {.cpp} -TGeoTranslation t1; -t1->SetTranslation(-5,10,4); -TGeoTranslation *t2 = new TGeoTranslation(4,3,10); -t2->Subtract(&t1); -``` - -- Rotations (**`TGeoRotation`** class) represent a pure rotation. Data - members are `Double_t fRotationMatrix[3*3]`. Rotations can be - defined either by Euler angles, either, by GEANT3 angles: - -``` {.cpp} -TGeoRotation *r1 = new TGeoRotation(); -r1->SetAngles(phi,theta,psi); // all angles in degrees -``` - -This represents the composition of: first a rotation about Z axis with -angle phi, then a rotation with theta about the rotated X axis, and -finally a rotation with `psi `about the new Z axis. - -``` {.cpp} -r1->SetAngles(th1,phi1,th2,phi2,th3,phi3) -``` - -This is a rotation defined in GEANT3 style. Theta and phi are the -spherical angles of each axis of the rotated coordinate system with -respect to the initial one. This construction allows definition of -malformed rotations, e.g. not orthogonal. A check is performed and an -error message is issued in this case. - -Specific utilities: determinant, inverse. - -- Scale transformations (**`TGeoScale`** class) - represent a scaled - shrinking/enlargement, possibly different on all axes. Data members: - `Double_t fScale[3]`. Not implemented yet. -- Combined transformations - represent a rotation followed by a - translation. Data members: - `Double_t fTranslation[3], `**`TGeoRotation *fRotation`.** - -``` {.cpp} -TGeoRotation *rot = new TGeoRotation("rot",10,20,30); -TGeoTranslation trans; -... -TGeoCombiTrans *c1 = new TGeoCombiTrans(trans,rot); -TGeoCombiTrans *c2 = new TGeoCombiTrans("somename",10,20,30,rot) -``` - -- General transformations: (**`TGeoHMatrix`** class) represent - combined transformations in any order. -- Identity transformation: (**`TGeoIdentity`** class) is a generic - identity transformation represented by a singleton class object - **`gGeoIdentity`**. - -### Ownership of Geometry Objects - -The class **`TGeoManager`** class contains the entire API needed for -building and tracking geometry. It defines a global pointer -***`gGeoManager`*** in order to be fully accessible from external code. -The manager class is the owner of all geometry objects defined in a -session; therefore, users must not try to control their deletion. It -contains lists of media, materials, transformations, shapes and volumes. -A special case is the one of geometrical transformations. When creating -a matrix or a translation, this is by default owned by external objects. -The manager class becomes owner of all transformations used for -positioning volumes. In order to force the ownership for other -transformations, one can use `TGeoMatrix::RegisterYourself()` method. Do -not be therefore surprised that some transformations cannot be found by -name when creating a composite shape for instance if you did not -register them after creation. - -Logical nodes (positioned volumes) are created and destroyed by the -**`TGeoVolume`** class. Physical nodes and their global transformations -are subjected to a caching mechanism due to the sometimes very large -memory requirements of logical graph expansion. The total number of -physical instances of volumes triggers the caching mechanism and the -cache manager is a client of **`TGeoManager`**. The manager class also -controls the drawing/checking package (**`TGeoPainter`** client). This -is linked with ROOT graphical libraries loaded on demand in order to -control visualization actions. - -## Navigation and Tracking - -Tracking is the feature allowing the transport of a given particle -knowing its kinematics. A state is determined by any combination of the -position $\vec{r}$ and direction $\vec{n}$ with respect to the world -reference frame. The direction $\vec{n}$ must be a unit vector having as -components the director cosines. The full classification of a given -state will provide the following information: the deepest physical node -containing the position vector, the distance to the closest boundary -along the direction vector, the next physical node after propagating the -current point with this distance and the safety distance to the nearest -boundary. This information allows the propagation of particles inside a -detector geometry by taking into account both geometrical and physical -constraints. - -We will hereby describe the user interface of **`TGeo`** to access -tracking functionality. This allows either developing a tracker for -simple navigation within a given geometry, either interfacing to an -external tracking engine such as GEANT. Note that the abstract interface -for external trackers can be found in `$ROOTSYS/vmc` folder and it can -be used to run GEANT3, GEANT4 and FLUKA-based simulations (\*) by using -directly a geometry described with ROOT. - -The interface methods related to tracking are incorporated into -**`TGeoManager`** class and implemented in the navigator class -**`TGeoNavigator`**. In order to be able to start tracking, one has to -define the initial state providing the starting point $\vec{r_0}$ - and direction $\vec{n_0}$ . -There are several ways of doing that. - -### TGeoNavigator Class - -One geometry may have several independent navigators to query to -localize points or compute distances. The geometry manager holds a list -of active navigators accessible via: - -``` {.cpp} -TObjArray *navigators = gGeoManager->GetListOfNavigators(); -``` - -Upon closing the geometry a default navigator is provided as first one -in this list, but one may add its own via: - -``` {.cpp} -TGeoNavigator *navig = new TGeoNavigator(gGeoManager); -// Store the index of the user navigator -Int_t inav = gGeoManager->AddNavigator(navig); -// Make its own navigator the active one -gGeoManager->SetCurrentNavigator(inav); -// Switch between navigators -gGeoManager->SetCurrentNavigator(0); -``` - -A navigator holds several variables describing the current navigation -state: current point position, current direction distance to next -boundary, isotropic safety, pointer to current and next nods as well as -several tracking flags related to volume boundary conditions or other -properties required for track propagation in geometry. Each geometry -query affects these variables, so the only way in testing several -navigation alternatives and remembering the active navigation state is -to use parallel navigation. The following paragraphs will describe the -usage of a single navigator. All setters/getters for navigation state -parameters as well as navigation queries provided by **`TGeoNavigator`** -are interfaced by **`TGeoManager`** and will act on the current -navigator. - -### Initializing the Starting Point - -The current point (`x,y,z`) known by the modeller is stored as -`Double_t fCurrentPoint[3]` by the navigator class. This array of the -three coordinates is defined in the current global reference system and -can be retrieved any time: - -``` {.cpp} -Const Double_t *cpoint = gGeoManager->GetCurrentPoint(); -``` - -Initializing this point can be done like: - -``` {.cpp} -gGeoManager->SetCurrentPoint(x,y,z); -// or: -gGeoManager->SetCurrentPoint(Double_t *point[3]); -``` - -### Initializing the Direction - -In order to move inside geometry starting with the current point, the -modeller needs to know the current direction `(nx,ny,nz)`. This -direction is stored as `Double_t fCurrentDirection[3]` by the navigator -and it represents a direction in the global frame. It can be retrieved -with: - -``` {.cpp} -Const Double_t *cdir = gGeoManager->GetCurrentDirection(); -``` - -The direction can be initialized in a similar manner as the current -point: - -``` {.cpp} -gGeoManager->SetCurrentDirection(nx,ny,nz); -// or: -gGeoManager->SetCurrentDirection(Double_t *dir); -``` - -### Initializing the State - -Setting the initial point and direction is not enough for initializing -tracking. The modeller needs to find out where the initial point is -located in the geometrical hierarchy. Due to the containment based -architecture of the model, this is the deepest positioned object -containing the point. For illustrating this, imagine that we have a -simple structure with a top volume `A` and another one `B `positioned -inside. Since `A `is a top volume, its associated node `A_1` will define -`MARS` and our simple hierarchy of nodes (positioned volumes) will be: -`/A_1/B_1`. Suppose now that the initial point is contained by `B_1`. -This implies by default that the point is also contained by `A_1`, since -`B_1` have to be fully contained by this. After searching the point -location, the modeller will consider that the point is located inside -`B_1`, which will be considered as the representative object (node) for -the current state. This is stored as: **`TGeoNode`** -\*`TGeoManager::fCurrentNode `and can be asked from the manager class -only after the `'Where am I?'` was completed: - -``` {.cpp} -TGeoNode *current = gGeoManager->GetCurrentNode(); -``` - -In order to find the location of the current point inside the hierarchy -of nodes, after setting this point it is mandatory to call the -`‘Where am I?'` method: - -``` {.cpp} -gGeoManager->FindNode(); -``` - -In order to have more flexibility, there are in fact several alternative -ways of initializing a modeller state: - -``` {.cpp} -// Setting the point and finding the state in one step: -gGeoManager->FindNode(Double_t x,Double_t y,Double_t z); -gGeoManager->FindNode(Double_t *point[3]); -// Setting both initial point and direction and finding the state: -gGeoManager->InitTrack(Double_t x,Double_t y,Double_t z, -Double_t nx, Double_t ny, Double_t nz); -gGeoManager->InitTrack(Double_t *point[3],Double_t *dir[3]); -``` - -Note that the current point coordinates can be changed and the state -re-initialized at any time. This represents the `‘Where am I?'` -geometrical query representing the basic navigation functionality -provided by the modeller. - -### Checking the Current State - -The current state and all variables related to this are essential during -tracking and have to be checked several times. Besides the current point -and direction, the following additional information can be retrieved -from **`TGeoManager`** interface: - -- The `current path`. This represents a string containing the names - and copy numbers of all positioned objects in the current `branch` - written in the /folder/folder/.../folder/file fashion. The final node - pointed by the path is the deepest object containing the current - point and is representative for the current state. All intermediate - `folders` in the path are in fact also nodes "touched" by the - current point, but having some "touched" containment. The current - path can be retrieved only after the state was initialized and is - useful for getting an idea of the current point location. - -``` {.cpp} -const char *path = gGeoManager->GetPath(); -cout << "Current path is: " << path << endl; -/A_1/B_34/C_3/D_1 -``` - -- The `current node`***`, `***`volume` and `material`. In order to - take decisions on post-step or further stepping actions, one has to - know these. In order to get a pointer to the current node one can - do: - -``` {.cpp} -TGeoNode *cnode = gGeoManager->GetCurrentNode(); -// then: -TGeoVolume *cvol = gGeoManager->GetCurrentVolume(); -// or: -cvol = cnode->GetVolume(); // (*) -// then: -TGeoMaterial *cmat = cvol->GetMedium()->GetMaterial(); -``` - -(\*) Note: If the current point is in fact outside the geometry, the -current node pointer will not be NULL, but pointing to the top node. - -In order to take decisions in such case one needs always to test: - -``` {.cpp} -if (gGeoManager->IsOutside()) { - // current point is actually outside - ... // corresponding action -} -``` - -Specific information related to the current volume/node like ID's or -shape can be then retrieved from the corresponding objects. - -- Current state `index`. The number of possible different states of - the modeller corresponds to the number of different objects/paths in - the geometry. This has nothing to do with the number of nodes, since - the same node can be found on different branches. In other words, - the number of states corresponds to the number of nodes in the - `expanded geometry tree`. Since unfortunately this expansion from - logical to physical hierarchy cannot be stored on regular basis due - to the large size of the latter, one cannot directly assign state - numbers. If the size of the expansion proves however to be small - enough (less than about 50 million objects), a parallel structure - storing these state indices is built and stored in memory. In such - case each state automatically gets an index that can be retrieved - after any state initialization. These indices can prove to be quite - useful for being able to keep track of the navigation history and - force certain states. Let's illustrate how this works with a simple - example: -- Suppose we have a simple geometry with a volume B positioned twice - inside a container A. Then A is positioned twice in a top container - T. The complete list of logical nodes is: `T_1`, `A_1`, `A_2`, - `B_1`, `B_2`. On the other hand we will have more states than - logical nodes: -- `/T_1`- 1 state at level = 0 -- `/T_1/A_1,/T_1/A_2`- 2 states at level = 1 -- `/T_1/A_1/B_1,/T_1/A_1/B_2,/T_1/A_2/B_1,/T_1/A_2/B_2` - 4 states at - level = 2 -- All these states will get automatic numbers, starting with 0 - corresponding to the top-level state and ending with an integer - corresponding to Ntotal\_states-1. The mapping from a given logical - node to a state number is generally not possible, as for the node - B\_1 that appears as current node for 2 different states. The - numbering order of states is therefore not important, but it can be - used as in the following lines: - -``` {.cpp} -gGeoManager->InitTrack(pt,dir); // anything to initialize a state -Int_t istate = gGeoManager->GetCurrentNodeId(); // in fact state Id -{ - //... code changing the current state -} -gGeoManager->CdNode(istate); // forces state's re-initialization -``` - -- Current `global transformation`. This represents the transformation - from `MARS` to the local reference of the current node, being the - product of all local mother-daughter transformations in the branch. - The global transformation can be referenced or copied: - -``` {.cpp} -const TGeoHMatrix *global = gGeoManager->GetCurrentMatrix(); -TGeoHMatrix *copy = new TGeoHMatrix(*global); -``` - -- One often needs to perform `master-to-local` and `local-to-master` - point and vector conversions to get from `MARS` to the local node - coordinates. This can be done by using the global transformation or - directly the **`TGeoManager`** corresponding interfaces: - -``` {.cpp} -Double_t *glob_pt = gGeoManager->GetCurrentPoint(); -Double_t *glob_dir = gGeoManager->GetCurrentDirection(); -Double_t loc_pt[3], loc_dir[3]; -// Go from MARS to local coordinates: -gGeoManager->MasterToLocal(glob_pt,loc_pt); // or: -global->MasterToLocal(glob_pt,loc_pt); // will be omitted from now -``` - -### Saving and Restoring the Current State - -As we already described, saving and restoring modeller states can be -quite useful during tracking and is a feature extensively used by -external tracking engines. We will call this navigation history -management, which in most of the cases can be performed by handling the -state identifiers. For quite big geometries, state indexing is not -possible anymore and will be automatically disabled by the modeller. -Fortunately there is a backup solution working in any condition: the -modeller maintains a stack of states that is internally used by its own -navigation algorithms, but user code is also allowed to access it. This -works on any stack principle by using PUSH and POP calls and user code -is responsible for popping the pushed states in order to keep the stack -clean. - -``` {.cpp} -// push the current state in the stack -Int_t index = gGeoManager->PushPath(); -// push state and current point -Int_t index = gGeoManager->PushPoint(); -// retrieves the last pushed state (decrements stack index) -gGeoManager->PopPath(); -// the same but retrieves also the point location -gGeoManager->PopPoint(); -// just decrement stack index without changing state -gGeoManager->PopDummy(); -// retrieves a state at given index without changing stack index -gGeoManager->PopPath(Int_t index); -``` - -### Navigation Queries - -After initializing the current state related to a given point and -direction defined in `MARS` `(‘Where am I?')`, one can query for several -geometrical quantities. All the related algorithms work in the -assumption that the current point has been localized inside the geometry -(by the methods `TGeoManager::FindNode()` or -**`TGeoManager`**`::InitTrack()`) and the current node or path has not -been changed by the user. - -#### Finding If Current State Is Changed For a New Point - -One can find fast if a point different from the current one has or not -the same location inside the geometry tree. To do that, the new point -should not be introduced by using `TGeoManager::SetCurrentPoint()` -method, but rather by calling the specific method: - -``` {.cpp} -Bool_t TGeoManager::IsSameLocation(Double_t x,Double_t y, -Double_t z,Bool_t change=kFALSE); -``` - -In the prototype above, `x, y` and `z` are the coordinates of the new -point. The modeller will check whether the current volume still contains -the new point or its location has changed in the geometry hierarchy. If -the new location is different, two actions are possible according to the -value of `change`: - -- `change = kFALSE` (default) - the modeller does not change the - current state but just inform the caller about this change. -- `change = kTRUE` - the modeller will actually perform a new - `‘Where am I?' `search after finding out that the location has - changed. The current state will be actualized accordingly. - -Note that even when performing a normal search on the current state -after changing the current point coordinates (e.g. -`gGeoManager->FindNode(newX,newY,newZ)`), users can always query if the -previous state has changed by using a method having the same name but -without parameters: - -``` {.cpp} -Bool_t TGeoManager::IsSameLocation(); -``` - -#### Finding the Distance to the Next Boundary - -All tracking engines need to compare the currently proposed physical -step with the maximum allowed distance in the current material. The -modeller provides this information by computing the distance to the -first boundary starting from the current point along a straight line. -The starting point and direction for this procedure are the ones -corresponding to the current state. The boundary search is initialized -inside the current volume and the crossed boundary can belong either to -the current node or to one of its daughters. The full prototype of the -method is: - -``` {.cpp} -TGeoNode *TGeoManager::FindNextBoundary(Double_t step=kBig); -``` - -In the prototype above, besides the current point and direction that are -supposed already initialized, the only input parameter is `step`. This -represents the maximum step allowed by the tracking algorithm or the -`physical step`. The modeller will search for a boundary crossing only -up to a distance equal to this value. If a boundary is found, a pointer -to the object (node) having it is returned; otherwise the method returns -`NULL`. - -The computed value for the computed distance can be subsequently -retrieved from the manager class: - -``` {.cpp} -Double_t snext = gGeoManager->GetStep(); -Double_t safety = gGeoManager->GetSafeDistance(); -``` - -According the step value, two use cases are possible: - -- `step =` `TGeoShape::kBig `(default behavior; `kBig = 1030`). In - this case, there is no limitation on the search algorithm, the first - crossed node is returned and the corresponding distance computed. If - the current point is outside geometry and the top node is not - crossed, the corresponding distance will be set to `kBig` and a - `NULL` pointer returned. No additional quantity will be computed. -- `step < kBig`. In this case, the progressive search starting from - the current point will be stopped after a distance equal with the - supplied step. In addition to the distance to the first crossed - boundary, the `safety radius` is also computed. Whenever the - information regarding the maximum required step is known it is - recommended to be provided as input parameter in order to speed-up - the search. - -In addition to the distance computation, the method sets an additional -flag telling if the current track will enter inside some daughter of the -current volume or it will exit inside its container: - -``` {.cpp} -Bool_t TGeoManager::IsStepEntering() const; -``` - -A combined task is to first find the distance to the next boundary and -then extrapolate the current point/direction with this distance making -sure that the boundary was crossed. Finally the goal would be to find -the next state after crossing the boundary. The problem can be solved in -principle using FindNextBoundary, but the boundary crossing can give -unpredictable results due to numerical roundings. The manager class -provides a method that allows this combined task and ensures boundary -crossing. This should be used instead of the method `FindNextBoundary()` -whenever the tracking is not imposed in association with an external MC -transport engine (which provide their own algorithms for boundary -crossing). - -``` {.cpp} -TGeoNode *TGeoManager::FindNextBoundaryAndStep(Double_t stepmax, -Bool_t comp_safe=kFALSE); -``` - -The meaning of the parameters here is the same as for FindNextBoundary, -but the safety value is triggered by an input flag. The output is the -node after the boundary crossing. - -#### Computing the Safe Radius - -Other important navigation query for tracking is the computation of the -safe distance. This represents the `maximum` step that can be made from -the current point in `any direction` that assures that no boundary will -be crossed. Knowing this value gives additional freedom to the stepping -algorithm to propagate the current track on the corresponding range -`without checking` if the current state has changed. In other words, the -modeller insures that the current state does not change in any point -within the safety radius around the current point. - -The computation of the safe radius is `automatically` computed any time -when the next boundary is queried within a `limited step:` - -``` {.cpp} -TGeoNode *crossed = gGeoManager->FindNextBoundary(pstep); -Double_t safety = gGeoManager->GetSafeDistance(); -``` - -Otherwise, the computation of safety can always be forced: - -``` {.cpp} -Double_t safety = gGeoManager->Safety(); -``` - -#### Making a Step - -The modeller is able to make steps starting from the current point along -the current direction and having the current step length. The new point -and its corresponding state will be automatically computed: - -``` {.cpp} -TGeoNode *TGeoManager::Step(Bool_t is_geom = kTRUE, -Bool_t cross = kTRUE); -``` - -We will explain the method above by its use cases. The input flag -`is_geom` allows specifying if the step is limited by geometrical -reasons (a boundary crossing) or is an arbitrary step. The flag cross -can be used in case the step is made on a boundary and specifies if user -wants to cross or not the boundary. The returned node represents the new -current node after the step was made. - -- Making a geometrically contained step with boundary crossing - (`is_geom=kTRUE`, `cross=kTRUE`) - This is the default method - behavior. In this case, the step size is supposed to be already set - by a previous `TGeoManager::FindNextBoundary()` call. Due to - floating-point boundary uncertainties, making a step corresponding - `exactly` to the distance to next boundary does not insure boundary - crossing. If the method is called with this purpose, an extra small - step will be made in order to make the crossing the most probable - event (`epsil=10-6cm`). Even with this extra small step cannot - insure 100% boundary crossing for specific crossed shapes at big - incident angles. After such a step is made, additional cross-checks - become available: - -``` {.cpp} -gGeoManager->FindNextBoundary(pstep); -Double_t snext = gGeoManager->GetStep(); -// The geometrical step is taken -TGeoNode *newNode = gGeoManager->Step(); -// The step=snext+epsil is made -Bool_t hasCrossed = gGeoManager->IsEntering(); -// Is the boundary crossed or not? -Bool_t isOnBoundary = gGeoManager->IsOnBoundary(); // The proposed -// geometrically limited step to be made was smaller -// than epsil value. -Bool_t isOutside = gGeoManager->IsOutside(); -//Did we exit geometry ? -``` - -In case the desired end-point of the step should be in the same starting -volume, the input flag `cross` should be set to `kFALSE`. In this case, -the `epsil` value will be subtracted from the current step. - -- Making a step of arbitrary value (`is_geom=kFALSE`, `cross=`no - matter). In this case, the step to be made can be either resulting - from a `next` computation, either set by hand: - -``` {.cpp} -gGeoManager->SetStep(stepvalue); -gGeoManager->Step(kFALSE); -``` - -The step value in this case will `exactly` match the desired step. In -case a boundary crossing failed after geometrically limited stepping, -one can force as many small steps as required to really cross the -boundary. This is not what generally happens during the stepping, but -sometimes small rounding of boundary positions may occur and cause -problems. These have to be properly handled by the stepping code. - -#### The Normal Vector to the Next Crossed Surface at Crossing Point - -Supposing we have found out that a particle will cross a boundary during -the next step, it is sometimes useful to compute the normal to the -crossed surface. The modeller uses the following convention: we define -as `normal` ($\vec{n}$) the unit vector perpendicular -to a surface in the `next crossing point`, having the orientation such -that: $\vec{n}.\vec{d}>0$. Here $\vec{d}$ -represents the current direction. The next crossing point represents the -point where a ray shot from the current point along the current -direction crosses the surface. - -``` {.cpp} -Double_t *TGeoManager::FindNormal(Bool_t forward=kTRUE); -``` - -The method above computes the normal to the next crossed surface in -forward or backward direction (i.e. the current one), assuming the state -corresponding to a current arbitrary point is initialized. An example of -usage of normal computation is ray tracing. - -The two most important features of the geometrical modeller concerning -tracking are scalability and performance as function of the total number -of physical nodes. The first refers to the possibility to make use of -the available memory resources and at the same time be able to resolve -any geometrical query, while the second defines the capability of the -modeller to respond quickly even for huge geometries. These parameters -can become critical when simulating big experiments like those at LHC. - -### Creating and Visualizing Tracks - -In case the modeller is interfaced with a tracking engine, one might -consider quite useful being able to store and visualize at least a part -of the tracks in the context of the geometry. The base class -**`TVirtualGeoTrack`** provides this functionality. It currently has one -implementation inside the drawing package (**`TGeoTrack`** class). A -track can be defined like: - -``` {.cpp} -TVirtualGeoTrack(Int_t id,Int_t pdg,TVirtualGeoTrack *parent=0, -TObject *particle=0); -``` - -Where: `id` is user-defined id of the track, `pdg` - `pdg` code, -`parent` - a pointer to parent track, `particle` - a pointer to an -arbitrary particle object (may be a **`TParticle`**). - -A track has a list of daughters that have to be filled using the -following method: - -``` {.cpp} -TVirtualGeoTrack *TVirtualGeoTrack::AddDaughter(Int_t id,Int_t pdg, -TObject *particle=0); -``` - -The method above is pure virtual and have to create a track daughter -object. Tracks are fully customizable objects when inheriting from -**`TVirtualGeoTrack`** class. We will describe the structure and -functionality provided by the default implementation of these, which are -**`TGeoTrack`** objects. - -A **`TGeoTrack`** is storing a list of `control points` `(x,y,z)` -belonging to the track, having also time information `(t)`. The painting -algorithm of such tracks allows drawing them in any time interval after -their creation. The track position at a given time is computed by -interpolation between control points. - -``` {.cpp} -myTrack->AddPoint(x,y,z,t); -``` - -The creation and management of tracks is in fact fully controlled by the -**`TGeoManager`** class. This holds a list of `primary tracks` that is -also visible during browsing as `Tracks` folder. Primary tracks are -tracks having no parent in the tracking history (for instance the output -of particle generators may be considered as primaries from tracking -point of view). The manager class holds -in**` TGeoManager::fCurrentTrack` a pointer to the current track. When -starting tracking a particle, one can create a track object like:** - -``` {.cpp} -Int_t track_index = gGeoManager->AddTrack(id,pdg,ptrParticle); -``` - -Here `track_index` is the index of the newly created track in the array -of primaries. One can get the pointer of this track and make it known as -current track by the manager class: - -``` {.cpp} -TVirtualGeoTrack *track = gGeoManager->GetTrack(track_index); -gGeoManager->SetCurrentTrack(track); -// or directly -gGeoManager->SetCurrentTrack(track_index); -TVirtualGeoTrack *current = gGeoManager->GetCurrentTrack(); -``` - -One can also look for a track by `user id` or `track index`: - -``` {.cpp} -ptrTrack = gGeoManager->GetTrackOfId(user_id); -ptrParent = gGeoManager->GetParentTrackOfId(user_id); -ptrTrack = gGeoManager->GetTrack(index); -``` - -Supposing a particle represented by a primary track decays or interacts, -one should not create new primaries as described before, but rather add -them as secondary: - -``` {.cpp} -TVirtualGeoTrack *secondary = -ptrTrack->AddTrack(secondId,pdg,secondParticle); -``` - -At any step made by the current track, one is able to add control points -to either primary or secondary: - -``` {.cpp} -track->AddPoint(x,y,z,t); -``` - -After tracks were defined and filled during tracking, one will be able -to browse directly the list of tracks held by the manager class. Any -track can be drawn using its `Draw()` and `Animate()` methods, but there -are also global methods for drawing or animation that can be accessed -from **`TGeoManager`** context menu: - -``` {.cpp} -TGeoManager::DrawTracks(Option_t *option); -TGeoManager::AnimateTracks(Double_t tmin=0.,Double_t tmax=1E-8, -Int_t nframes=200,Option_t *option=""); -``` - -The drawing/animation time range is a global variable that can be -directly set: - -``` {.cpp} -gGeoManager->SetTminTmax(tmin, tmax); -// without arguments resets the time range to the maximum value -``` - -Once set, the time range will be active both for individual or global -track drawing. For animation, this range is divided to the desired -number of frames and will be automatically updated at each frame in -order to get the animation effect. - -The option provided to all track-drawing methods can trigger different -track selections: - -`default: `A track (or all primary tracks) drawn without daughters - -`/D:` Track and first level descendents only are drawn - -`/*: ` Track and all descendents are drawn - -`/Ntype:` All tracks having `name=type` are drawn - -Generally several options can be concatenated in the same string (E.g. -`"/D /Npion-"`). - -For animating tracks, additional options can be added: - -`/G:`Geometry animate. Generally when drawing or animating tracks, one -has to first perform a normal drawing of the geometry as convenient. The -tracks will be drawn over the geometry. The geometry itself will be -animated (camera moving and rotating in order to "catch" the majority of -current track segments.) - -`/S:`Save all frames in gif format in the current folder. This option -allows creating a movie based on individual frames. - -## Checking the Geometry - -Several checking methods are accessible from the context menu of volume -objects or of the manager class. They generally apply only to the -visible parts of the drawn geometry in order to ease geometry checking, -and their implementation is in the **`TGeoChecker`** class. The checking -package contains an overlap checker and several utility methods that -generally have visualization outputs. - -### The Overlap Checker - -An overlap is any region in the Euclidian space being contained by more -than one positioned volume. Due to the containment scheme used by the -modeller, all points inside a volume have to be also contained by the -mother therefore are overlapping in that sense. This category of -overlaps is ignored due to the fact that any such point is treated as -belonging to the deepest node in the hierarchy. - -![Extruding volumes](pictures/030001DE.png) - -A volume containment region is in fact the result of the subtraction of -all daughters. On the other hand, there are two other categories of -overlaps that are considered illegal since they lead to unpredictable -results during tracking. - -A) If a positioned volume contains points that are not also contained -by its mother, we will call the corresponding region as an `extrusion`. -When navigating from outside to inside (trying to enter such a node) -these regions are invisible since the current track has not yet reached -its mother. This is not the case when going the other way since the -track has first to exit the extruding node before checking the mother. -In other words, an extrusion behavior is dependent on the track -parameters, which is a highly undesirable effect. - -B) We will call ***`overlaps`*** only the regions in space contained by -more than one node inside the same container. The owner of such regions -cannot be determined based on hierarchical considerations; therefore -they will be considered as belonging to the node from which the current -track is coming from. - -When coming from their container, the ownership is totally -unpredictable. Again, the ownership of overlapping regions highly -depends on the current track parameters. - -We must say that even the overlaps of type A) and B) are allowed in case -the corresponding nodes are created using -**`TGeoVolume`**`::AddNodeOverlap()` method. Navigation is performed in such -cases by giving priority to the non-overlapping nodes. The modeller has -to perform an additional search through the overlapping candidates. -These are detected automatically during the geometry closing procedure -in order to optimize the algorithm, but we will stress that extensive -usage of this feature leads to a drastic deterioration of performance. -In the following we will focus on the non-declared overlaps of type A) -and B) since this is the main source of errors during tracking. These -are generally non-intended overlaps due to coding mistakes or bad -geometry design. The checking package is loaded together with the -painter classes and contains an automated overlap checker.** - -![Overlap checking](pictures/030001DF.png) - -This can be activated both at volume level (checking for illegal -overlaps only one level inside a given volume) and from the geometry -manager level (checking full geometry): - -``` {.cpp} -myVolume->CheckOverlaps(precision, option); -gGeoManager->CheckOverlaps(precision); -myNode->CheckOverlaps(precision); -``` - -Here precision represents the desired maximum accepted overlap value in -centimeters (default value is 0.1). This tool checks all possible -significant pairs of candidates inside a given volume (not declared as -overlapping or division volumes). The check is performed by verifying -the mesh representation of one candidate against the shape of the other. -This sort of check cannot identify all possible overlapping topologies, -but it works for more than 95% and is much faster than the usual -shape-to-shape comparison. For a 100% reliability, one can perform the -check at the level of a single volume by using `option`="`d`" or -`option`="`d`" to perform overlap checking by sampling the -volume with \<`number`\> random points (default 1 million). This -produces also a picture showing in red the overlapping region and -estimates the volume of the overlaps. - -An extrusion A) is declared in any of the following cases: - -- At least one of the vertices of the daughter mesh representation is - outside the mother volume (in fact its shape) and having a safety - distance to the mother greater than the desired value; -- At least one of the mother vertices is contained also by one of its - daughters, in the same conditions. - -An overlap B) is declared if: - -- At least one vertex of a positioned volume mesh is contained (having - a safety bigger than the accepted maximum value) by other positioned - volume inside the same container. The check is performed also by - inverting the candidates. - -The code is highly optimized to avoid checking candidates that are far -away in space by performing a fast check on their bounding boxes. Once -the checking tool is fired-up inside a volume or at top level, the list -of overlaps (visible as Illegal overlaps inside a **`TBrowser`**) held -by the manager class will be filled with **`TGeoOverlap`** objects -containing a full description of the detected overlaps. The list is -sorted in the decreasing order of the overlapping distance, extrusions -coming first. An overlap object name represents the full description of -the overlap, containing both candidate node names and a letter -(x-extrusion, o-overlap) representing the type. Double-clicking an -overlap item in a **`TBrowser`** produces a picture of the overlap -containing only the two overlapping nodes (one in blue and one in green) -and having the critical vertices represented by red points. The picture -can be rotated/zoomed or drawn in X3d as any other view. Calling -`gGeoManager->PrintOverlaps()` prints the list of overlaps. - -### Graphical Checking Methods - -![Safety computation checking](pictures/030001E0.png) - -In order to check a given point, `CheckPoint(x,y,z)` method of -**`TGeoManager`** draws the daughters of the volume containing the point -one level down, printing the path to the deepest physical node holding -this point. It also computes the closest distance to any boundary. - -![Random points](pictures/030001E1.png) - -A method to check the validity of a given geometry is shooting random -points. This can be called with the method -**`TGeoVolume`**`::RandomPoints()` and it draws a volume with the current -visualization settings. Random points are generated in the bounding box -of the drawn volume. The points are drawn with the color of their -deepest container. Only points inside visible nodes are drawn. - -![Random rays](pictures/030001E2.png) - -A ray tracing method can be called `TGeoVolume::RandomRays()`. This -shoots rays from a given point in the local reference frame with random -directions. The intersections with displayed nodes appear as segments -having the color of the touched node. - -## The Drawing Package - -![](pictures/030001E3.png)The modeller provides a powerful drawing -package, supporting several different options of visualization. A -library separated from the main one provides all functionality being -linked with the underlying ROOT visualization system. This library is -dynamically loaded by the plug-in manager only when drawing features are -requested. The geometrical structures that can be visualized are volumes -and volume hierarchies. - -The main component of the visualization system is volume primitive -painting in a ROOT pad. Starting from this one, several specific options -or subsystems are available, like: X3D viewing using hidden line and -surface removal algorithms, OpenGL viewing\* or ray tracing. - -The method `TGeoManager::GetGeomPainter()`loads the painting library in -memory. - -This is generally not needed since it is called automatically by -`TGeoVolume::Draw()` as well as by few other methods setting -visualization attributes. - -### Drawing Volumes and Hierarchies of Volumes - -The first thing one would like to do after building some geometry is to -visualize the volume tree. This provides the fastest validation check -for most common coding or design mistakes. As soon as the geometry is -successfully closed, one should draw it starting from the top-level -volume: - -``` {.cpp} -//... code for geometry building -root[] gGeoManager->CloseGeometry(); -root[] gGeoManager->GetMasterVolume()->Draw(); -``` - -Doing this ensures that the original top-level volume of the geometry is -drawn, even if another volume is currently the geometry `root`. OK, I -suppose you already did that with your simple geometry and immediately -noticed a new ROOT canvas popping-up and having some more or less -strange picture inside. Here are few questions that might come: - -***`Q:`*** "The picture is strangely rotated; where are the coordinate axes?" - -***`A:`*** If drawn in a new canvas, any view has some default -viewpoint, center of view and size. One can then perform mouse/keyboard -actions to change them: - -- Mouse left-click and drag will rotate the view; - -- Some keys can be pressed when the view canvas is selected: J/K -zoom/un-zoom, U/I move up/down, L/H move left/right. The coordinate axes -display as well as changing top or side viewpoints can be activated from -the **`TView`** context menu: right-click on the picture when no object -is selected; - -***`Q:`*** "Every line is black! I cannot figure out what is what..." - -***`A:`*** Volumes can have different colors (those known by ROOT of -course). Think at using them after each volume creation: -`myvolume->SetLineColor(Int_t color);` otherwise everything is by -default black. - -***`Q:`*** "The top volume of my geometry is a box but I see only its content." - -***`A:`*** By default the drawn volume is not displayed just because we -do not want to hide its content when changing the view to HLR or solid -mode. In order to see it in the default wire frame picture one has to -call **`TGeoManager::SetTopVisible()`.** - -***`Q:`*** "I do not see all volumes in my tree but just something inside." - -***`A:`*** By default, **`TGeoVolume`**`::Draw()` paints the content of -a given volume three levels down. You can change this by using: -***`gGeoManager`***`::SetVisLevel(n);` - -Not only that, but none of the volumes at intermediate levels (0-2) are -visible on the drawing unless they are final ‘leaves' on their branch -(e.g. have no other volumes positioned inside). This behavior is the -default one and corresponds to ‘leaves' global visualization mode -(**`TGeoManager::fVisOption = 1`). In order to see on the screen the -intermediate containers, one can change this mode: -`gGeoManager->SetVisOption(0)`.** - -***`Q:`*** "Volumes are highlighted when moving the mouse over their vertices. What does it mean?" - -***`A:`*** Indeed, moving the mouse close to some volume vertices -selects it. By checking the `Event Status` entry in the root canvas -`Options` menu, you will see exactly which is the selected node in the -bottom right. Right-clicking when a volume is selected will open its -context menu where several actions can be performed (e.g. drawing it). - -***`Q:`*** "OK, but now I do not want to see all the geometry, but just a particular volume and its content. How can I do this?" - -***`A:`*** Once you have set a convenient global visualization option -and level, what you need is just call the `Draw()` method of your -interesting volume. You can do this either by interacting with the -expanded tree of volumes in a ROOT browser (where the context menu of -any volume is available), either by getting a pointer to it (e.g. by -name): `gGeoManager->GetVolume("vol_name")->Draw();` - -### Visualization Settings and Attributes - -Supposing you now understand the basic things to do for drawing the -geometry or parts of it, you still might be not happy and wishing to -have more control on it. We will describe below how you can fine-tune some - settings. Since the corresponding attributes are flags belonging to -volume and node objects, you can change them at any time (even when the -picture is already drawn) and see immediately the result. - -#### Colors and Line Styles - -We have already described how to change the line colors for volumes. In -fact, volume objects inherit from TAttLine class so the line style or -width can also be changed: - -``` {.cpp} -myVolume->SetLineColor(kRed); -myVolume->SetLineWith(2); -myVolume->SetLineStyle(kDotted); -``` - -When drawing in solid mode, the color of the drawn volume corresponds to -the line color. - -#### Visibility Settings - -The way geometry is build forces the definition of several volumes that -does not represent real objects, but just virtual containers used for -grouping and positioning volumes together. One would not want to see -them in the picture. Since every volume is by default visible, one has -to do this sort of tuning by its own: - -``` {.cpp} -myVolumeContainer->SetVisibility(kFALSE); -``` - -As described before, the drawing package supports two main global -options: 1 (default) - only final volume leaves; 0 - all volumes down -the drawn one appear on the screen. The global visible level put a -limitation on the maximum applied depth. Combined with visibility -settings per volume, these can tune quite well what should appear on the -screen. However, there are situations when users want to see a volume -branch displayed down to the maximum depth, keeping at the same time a -limitation or even suppressing others. In order to accomplish that, one -should use the volume attribute: `Visible daughters`. By default, all -daughters of all volumes are displayed if there is no limitation related -with their level depth with respect to the top drawn volume. - -### Ray Tracing - -Ray tracing is a quite known drawing technique based on tracking rays -from the eye position through all pixels of a view port device. The -pixel color is derived from the properties of the first crossed surface, -according some illumination model and material optical properties. While -there are currently existing quite sophisticated ray tracing models, -**`TGeo`** is currently using a very simple approach where the light -source is matching the eye position (no shadows or back-tracing of the -reflected ray). In future we are considering providing a base class in -order to be able to derive more complex models. - -Due to the fact that the number of rays that have to be tracked matches -the size in pixels of the pad, the time required by this algorithm is -proportional to the pad size. On the other hand, the speed is quite -acceptable for the default ROOT pad size and the images produced by -using this technique have high quality. Since the algorithm is -practically using all navigation features, producing ray-traced pictures -is also a geometry validation check. Ray tracing can be activated at -volume level as the normal `Draw()`. - -![Ray-traced view in a pad](pictures/020001E4.jpg) - -``` {.cpp} -myVolume->Raytrace() -``` - -Once ray-tracing a view, this can be zoomed or rotated as a usual one. -Objects on the screen are no longer highlighted when picking the -vertices but the corresponding volumes is still accessible. - -#### Clipping Ray-traced Images - -A ray-traced view can be `clipped` with any shape known by the modeller. -This means that the region inside the clipping shape is subtracted from -the current drawn geometry (become invisible). In order to activate -clipping, one has to first define the clipping shape(s): - -`1. TGeoShape *clip1, *clip2, ...` - -One might switch between several clipping shapes. Note that these shapes -are considered defined in the current `MARS`. Composite shapes may be -used. - -2`. gGeoManager->SetClippingShape(clip1);` - -One can activate or deactivate clipping at any time: -`gGeoManager->SetClipping(flag);` - -3. Perform ray-tracing:` gGeoManager->GetTopVolume()->Raytrace();` - -One can redo the steps 2-3 as many times as needed. Let us look how the -***`rootgeom`*** example looks clipped with a tube. - -![Ray-tracing example with box-clipping](pictures/030001E5.png) - -## Representing Misalignments of the Ideal Geometry - -The ideal positioning of a detector does not match its position in the -experimental hall. This generally happens not only for the detector -modules, but also for their components. The accurate knowledge of the -detector real misalignments can be extremely important for getting close -to its designed resolution and the expected tracking efficiency. -**`TGeo`** offers tools for representing positioning misalignments, -applying them to the ideal geometry and performing navigation under -these conditions. Detector tracking algorithms can then directly query -the geometry for navigation purposes or for retrieving actual -misalignment information. - -### Physical Nodes - -Physical nodes are the actual "touchable" objects in the geometry, -representing actually a path of positioned volumes starting with the -top node: `path=/TOP/A_1/B_4/C_3` , where `A`, `B`, `C` represent names -of volumes. The number of physical nodes is given by the total number of -possible of branches in the geometry hierarchy. In case of detector -geometries and specially for calorimeters this number can be of the -order 106-109, therefore it is impossible to create all physical nodes -as objects in memory. In **`TGeo`**, physical nodes are represented by -the class **`TGeoPhysicalNode`** and can be created on demand for -alignment purposes: - -``` {.cpp} -TGeoPhysicalNode(const char* path) -``` - -The knowledge of the path to the objects that need to be misaligned is -essential since there is no other way of identifying them. One can -however create "symbolic links" to any complex path to make it more -representable for the object it designates: - -``` {.cpp} -TGeoPNEntry(const char* unique_name, const char* path) -void TGeoPNEntry::SetPhysicalNode(TGeoPhysicalNode *node) -``` - -Such a symbolic link hides the complexity of the path to the align -object and replaces it with a more meaningful name. In addition, -**`TGeoPNEntry`** objects are faster to search by name and they may -optionally store an additional user matrix. - -``` {.cpp} -// Creating a symlink object. -TGeoPNEntry *TGeoManager::SetAlignableEntry(const char *unique_n, -const char*path) -// Retrieving an existing alignable object. -TGeoPNEntry *TGeoManager::GetAlignableEntry(const char *name) -// Retrieving an existing alignable object at a given index. -TGeoPNEntry *GetAlignableEntry(Int_t index) -``` - -Physical nodes store internally the full list of logical nodes -corresponding to the elements from the string path, as well as the -global transformation matrix for each of them. The top node corresponds -to the level 0 in the stored array, while the last node will correspond -to level `n`. For each level, the node, volume and global matrix can be -retrieved using corresponding getters: - -``` {.cpp} -TGeoHMatrix *GetMatrix(Int_t level=-1) const -TGeoNode *GetNode(Int_t level=-1) const -TGeoShape *GetShape(Int_t level=-1) const -TGeoVolume *GetVolume(Int_t level=-1) const -``` - -By default the object at level n is retrieved (the align-able object). - -Once created, a physical node can be misaligned, meaning that its -positioning matrix or even the shape.: - -``` {.cpp} -void Align(TGeoMatrix* newmat=0, TGeoShape* newshape=0, -Bool_t check=kFALSE) -``` - -The convention used is that newmat represents the new local matrix of -the last node in the branch with respect to its mother volume. The -`Align()` method will actually duplicate the corresponding branch within -the logical hierarchy, creating new volumes and nodes. This is mandatory -in order to avoid problems due to replicated volumes and can create -exhaustive memory consumption if used abusively. - -Once aligned, a physical node is ready to be tracked. The operation can -be done only after the geometry was closed. - -Important NOTE: Calling the `Align()` method for a physical node changes -the node pointers for the stored node branch in the active geometry, Due -to this the other defined physical nodes containing elements of this -path will be invalid. Example: - -``` {.cpp} -TGeoPhysicalNode *pn1 = -gGeoManager->MakePhysicalNode("/A_1/B_1/C_2"); -TGeoPhysicalNode *pn2 = -gGeoManager->MakePhysicalNode("/A_1/B_1/C_3"); -... -pn1->Align(...); -``` - -The call to `pn1->Align()` will invalidate the pointer to the node `B_1` -in `pn2` object.. The way out is to either call `pn1->Align()` before -the creation of `pn2`, either to use a global method that will correct -all existing physical nodes: - -``` {.cpp} -void RefreshPhysicalNodes(Bool_t lock = kTRUE) -``` - -The method above will optionally lock the possibility of doing any -further misalignment. - -## Geometry I/O - -Once geometry is successfully built, it can be saved in a root file, as -C++ macro or as GDML file by calling: - -``` {.cpp} -TGeoManager::Export(const char *filename,const char*keyname="", -Option_t *opt="vg") -``` - -- `Filename`is the name of the file to be written (mandatory). - Depending on the extension of the file, the geometry is exported - either as ,root file or .C(.cxx) macro or GDML file in case - extension is .gdml. -- `keyname`is the name of the key in the file (default "") -- `opt` = `"v"` is an export voxelization (default), otherwise - voxelization is recomputed after loading the geometry, `"g"` this - option (default) is taken into account only for exporting to gdml - file and it ensures compatibility with Geant4 (e.g. it adds extra - plane to incorrectly set polycone, it checks whether offset of Phi - division is in (-360;0\> range, ...), for this gdml export there are - two more option, that are not set by default: `"f"` and `"n"`. If - none of this two options are set, then names of solids and volumes - in resulting gdml file will have incremental suffix (e.g. - TGeoBBox\_0x1, TGeoBBox\_0x2, ...). If `"f"` option is set then then - suffix will contain pointer of object (e.g. TGeoBBox\_0xAAAAA01, - ...). Finally if option `"n"` is set then no suffix will be added, - though in this case uniqueness of the names is not ensured and it can - cause that file will be invalid. - -Loading geometry from a root file can be done in the same way as for any -other ROOT object, but a static method is also provided: - -``` {.cpp} -TGeoManager::Import(const char *filename,const char *keyname="", -Option_t *opt="") -``` - -Example: - -``` {.cpp} -// Writing to a file geometry definition ending with: -root[] gGeoManager->CloseGeometry(); -// geometry is ready -root[] gGeoManager->Export("MyGeom.root"); -// file MyGeom.root produced -root[] gGeoManager->Export("MyGeom.C"); - // C++ macro MyGeom.C produced -root[] gGeoManager->Export("MyGeom.gdml"); - // GDML file MyGeom.gdml produced -root[] myVolume->SaveAs("MyVolume.C"); - // C++ macro for the branch starting - // with MyVolume -// Reading from a file -root[] gSystem->Load("libGeom"); -root[] TGeoManager::Import("MyGeom.root"); // geometry is ready -``` - -Note that not all-current information held by the modeller is written on -the file. For instance, the painter and checker objects are not written, -as well as the temporary current navigation properties: current node -path, point or direction. On the other hand, all objects belonging to -the geometrical hierarchy will always be written. The idea is to be able -to retrieve the geometry in a ready state, ignoring what the state -variables that can be always re-initialized. When the code is generated -for a given **`TGeoVolume`** in the geometry, just the branch starting -with that volume will be saved in the file. Executing the generated code -will create a geometry that has `MyVolume` as top volume. In this case, -only the materials/media/matrices used effectively in the `MyVolume` -branch are exported to file. - -Volumes can be made persistent in the same way the full geometry is. -Exporting is straightforward (module1, 2 are pointers to -**`TGeoVolume`** objects): - -``` {.cpp} -module1->Export("file.root"); -// by default file is overwritten -module2->Export("file.root","","update"); -// to the same file -``` - -Importing will append the volume to the current TGeoManager or will -create one: - -``` {.cpp} -TGeoManager *geom = new TGeoManager("myGeom", ""); -TGeoVolume *top = geom->MakeBox(...); -geom->SetTopVolume(top); -//name of volume or key (depending on export usage) -TGeoVolume *module1 = TGeoVolume::Import("file.root", "MOD1"); -TGeoVolume *module2 = TGeoVolume::Import("file.root", "MOD2"); -top->AddNode(module1, 1, new TGeoTranslation(0,0,100)); -top->AddNode(module2, 1, new TGeoTranslation(0,0,-100)); -// One should close oneself the geometry -geom->CloseGeometry(); -``` - -### GDML - -Few lines above word GDML was used. GDML stands for **G**eometry -**D**escription **M**arkup **L**anguage. It is an application-independent -geometry description format based on XML. It is mainly used for geometry -interchange between ROOT and Geant4 framework. More details about this -project can be found http://gdml.web.cern.ch. This feature -(importing/exporting from/to gdml file format) is disabled by default in -ROOT installation. To enable this feature add `--enable-gdml` option to -`./configure` script call. - -## Navigation Algorithms - -This section will describe the main methods and algorithms used for -implementing the navigation features within the geometrical modeller. -This includes navigation queries at shape level, global geometrical -queries and optimization mechanisms. - -### Finding the State Corresponding to a Location (x,y,z) - -For reminder, a geometry state is a ‘touchable' object in the geometry -hierarchy. It is represented by a path like: **/TOP\_1/A\_1/B\_3/C\_1**, -where **B\_3** for instance is a copy of volume **B** positioned inside -volume **A**. A state is always associated to a transformation matrix -**M** of the touchable with respect to the global reference frame -(obtained by piling-up all local transformations of nodes in the branch -with respect to their containers). The current state and the -corresponding global matrix are updated whenever the geometry depth is -modified. The global transformations corresponding to all nodes in the -current branch are kept in an array: (**MTOP\_1, MA\_1, MB\_3, ...**). - -![Navigation in the geometry hierarchy](pictures/080001E6.png) - -The elementary operations for changing the state are: - -``` {.cpp} -TGeoManager::CdUp(); -TGeoManager::CdDown(i); -TGeoManager::CdTop() -``` - -The current state accounting and global matrix handling after these -operations are depicted in the figure below. Now let us suppose that we -have a particle at position *P(x,y,z)*. The first thing needed for -transporting it is the current object our particle is into, so that we -can retrieve its material properties. This task is done by: - -``` {.cpp} -TGeoNode *TGeoManager::FindNode(x,y,z) -``` - -Note that the current particle position can be set using -**`SetCurrentPosition(x,y,z)`** method of the manager class, in which -case **`FindNode()`** can be called without arguments. The method -returns a pointer to the *deepest node* that geometrically contains *P* -(in our case let us suppose it is *B\_3*). Since a node is just a -positioned volume, we can then get a pointer to the volume, medium or -material objects related to it. *Deepest* means that *B\_3* still -contains point *P* (as well as *A\_1* and *TOP\_1*), but none of the -daughters of volume **B** does. After finding out the node containing -the particle, one can check if the geometry state is different compared -to the last located point: - -``` {.cpp} -Bool_t *TGeoManager::IsSameLocation() -``` - -The algorithm for finding where a point is located in geometry is -presented in the figure 17-36. - -It always starts by checking if the last computed modeller state is the -answer. This optimizes the search when continuously tracking a particle. -The main actions performed are: - -- moving up and down in the logical node tree while updating the - current node and its global matrix -- converting the global position into the local frame of the current - node/volume -- checking whether the local position lies within the geometrical - shape of the current volume - if this is the case continue the - search downwards for the daughters of the current node, otherwise - search upwards its containers until the top level is reached. -- the number of candidate nodes to be checked at a given level is - minimized by an additional optimization structure: voxels. This is - effective even in case there is only one daughter of the current - volume. -- in case the current node is declared as possibly overlapping, the - method FindInCluster() is invoked. This method checks all different - possibilities within the cluster of overlapping candidates. One of - the candidates is prioritized if one of the following conditions id - fulfilled (in order): -- Is declared as non-overlapping (these are anyway searched first) -- Has at least one daughter that contains the current point -- Was already declared as containing the point at a previous step - -![Finding the location of a point in the geometry hierarchy](pictures/080001E7.png) - -### Finding the Distance to Next Crossed Boundary - -The most important feature provided by the modeller related to track -propagation is the computation of the distance to the next boundary -along a straight line. - -The relevant state parameters used for this task are: - -- Current particle position and direction `(x,y,z,nx,ny,nz)`, where ni - is the direction cosine with axis (`i`). -- Current node (and path) in geometry must be set by calling - `TGeoManager::FindNode(x,y,z) `beforehand The method computing the - distance to next boundary is: - -``` {.cpp} -TGeoNode *TGeoManager::FindNextBoundary(stepmax, path) -``` - -The output node returned by the method is the object which shape -boundary will be crossed first. The distance to the next crossing can be -retrieved after the call: - -``` {.cpp} -Double_t TGeoManager::GetStep() -``` - -- The main input parameter is `stepmax,` which act as a trigger for - different features. The absolute value of this parameter represents - the step value proposed by the user. The algorithm will never try o - search for boundaries further than this distance. In case no - boundary is found the returned node will be the current one and the - computed step to boundary will be equal to abs (`stepmax`) having - the meaning *"step approved"*. The default value for `stepmax` is - `TGeoShape::Big `with the meaning that boundaries are looked for - without limitation. - -![Finding the distance to the next crossed boundary](pictures/080001E8.png) - -According the values of the input parameters the method will perform -additional optional tasks: - -**`|stepmax| < `** ***`TGeoShape::Big()`*** **` `** - -The safe distance in the current volume is also computed. Moving the -particle from its current location with this distance in any direction -is safe in the sense that will never change the current state. - -**`stepmax < 0`** - -The global matrix for the object that will have the next crossed -boundary is also computed. This can be retrieved for masterlocal point -or vector conversions: **`TGeoManager`**::`GetNextMatrix`() - -In case the computation of the normal vector to the next crossed surface -is required, using a negative stepmax value is recommended. In this case -one can subsequently call a method for fast normal computation: - -``` {.cpp} -Double_t *TGeoManager::FindNormalFast() -``` - -**`path `** **` 0`** - -In case a path to a given physical object is specified, the distance to -its boundary is computed ignoring the rest of the geometry - -#### Output Values - -`TGeoManager::GetStep()`: distance to next boundary. - -`TGeoManager::GetSafeDistance()`: safe distance (in case it was -computed). - -`TGeoManager::IsOnBoundary()`: the initial point `(x,y,z)` was (or was -not) on a boundary within `TGeoShape::Tolerance()`. - -The algorithm checks first if the computation of safety was required. If -this is the case and the global point coordinates did not change from -the last query, the last computed safety is taken. Otherwise, the method -**`TGeoManager`**`::Safety ()` is invoked. A safety value less than -**`TGeoShape`**`::Tolerance()` will set the flag IsOnBoundary to true. -On the other hand, a safety value bigger than the proposed step will -stop the computation of the distance to next boundary, returning the -current geometry location with the meaning that the proposed step is -safe. - -The next stage is to check if computation of the distance to a give -physical object specified by a path was required. If this is the case, -the modeller changes the state to point to the required object, converts -the current point and direction coordinates to the local frame of this -object and computes the distance to its shape. The node returned is the -one pointed by the input path in case the shape is crossed; otherwise -the returned value is NULL. In case the distance to next crossed -boundary is required, the current point has to be physically INSIDE the -shape pointed by the current volume. This is only insured in case a call -to `TGeoManager::FindNode()` was performed for the current point. -Therefore, the first step is to convert the global current point and -direction in the local reference frame of the current volume and to -compute the distance to exit its shape from inside. The returned value -is again compared to the maximum allowed step (the proposed one) and in -case the distance is safe no other action is performed and the proposed -step is approved. In case the boundary is closer, the computed distance -is taken as maximum allowed step. For optimization purposed, for -particles starting very close to the current volume boundary (less than -0.01 microns) and exiting the algorithm stops here. - -After computing the distance to exit the current node, the distance to -the daughter of the current volume which is crossed next is computed by -**`TGeoManager`**`::FindNextDaughterBoundary().` This computes the -distance to all daughter candidates that can be possibly crossed by -using volume voxelization. The algorithm is efficient in average only in -case the number of daughters is greater than 4. For fewer nodes, a -simple loop is performed and the minimum distance (from a point outside -each shape) is taken and compared to the maximum allowed step. The step -value is again updated if `stepGetCurrentPoint(); -Double_t *current_dir = gGeoManager->GetCurrentDirection(); -for (Int_t i=0; i<3; i++) - current_point[i] += step * current_dir[I]; -``` - -Note: The method `TGeoManager::FindNextBoundary()` does not modify the -current point/direction nor the current volume/state. The returned node -is the next crossed one, but the physical path (state) AFTER crossing -the boundary is not determined. In order to find out this new state, one -has to propagate the point with a distance slightly bigger that the -computed step value (which is accurate within numerical precision). A -method that performs this task finding the next location is -`TGeoManager::Step()`, described in " Making a Step ", but users may -implement more precise methods to insure post-step boundary crossing. - -## Geometry Graphical User Interface - -The geombuilder package allows you to create and edit geometries. The -package provides a library of all GUI classes related to geometry. Each -editable geometry class **`TGeoXXX`** have a correspondent editor -**`TGeoXXXEditor`** that provides a graphics user interface allowing to -edit some (or all) parameters of a geometry object. The editable objects -are geometry manager, volumes, nodes, shapes, media, materials and -matrices. The interfaces provide also access to specific functionality -of geometry objects. The editing mechanism is based on ROOT GED -(Graphics Editors) functionality and the library is loaded using the -plug-in mechanism. - -### Editing a Geometry - -There are two different use cases having different ways of invoking the -geometry editors. The first one applies when starting with geometry from -scratch and using the builder functionality to create new geometry -objects. In this case, one should use the sequence: - -``` {.cpp} -root[] TGeoManager *geom = new TGeoManager("MyGeom", -"Test builder"); -root[] geom->Edit(Option_t *option=""); -``` - -The lines above will create a new **`TGeoManager`** class, create an -empty canvas and start the editor in the left-sided editor frame -attached to the canvas. To open the editor in a separate frame one -should provide a non-empty string as option to the `Edit()` method. - -![The geometry manager editor](pictures/030001E9.png) - -### The Geometry Manager Editor - -![Accessing/creating different categories of editable -objects](pictures/020001EA.jpg) ![Accessing/creating different -categories of editable objects](pictures/020001EB.jpg) -![Accessing/creating different categories of editable -objects](pictures/020001EC.jpg) ![Accessing/creating different -categories of editable objects](pictures/020001ED.jpg) -![Accessing/creating different categories of editable -objects](pictures/020001EE.jpg) - -The second use case applies when starting to edit an existing geometry. -Supposing the geometry was loaded into memory, besides the first method -that still applies one can also edit drawn geometry objects. For this, -the menu entry View/Editor of the canvas containing for instance a drawn -volume must be activated. For starting the volume editor one can click -on a volume. The GUI of the **`TGeoManager`** class can be started by -clicking on the top-right `40x40` pixels corner of the pad with a drawn -geometry. - -This is the main entry point for editing the geometry or creating new -objects. Once the interface is created (using one of the methods -described above), several categories can be accessed via a shutter GUI -widget: - -- *General.* This allows changing the name/title of the geometry, - setting the top volume, closing the geometry and saving the geometry - in a file. The file name is formed by `geometry_name.C` or `.root` - depending if the geometry need to be saved as a `C` macro or a - `.root` file. -- *Shapes.* The category provides buttons for creation of all - supported shapes. The new shape name is chosen by the interface, but - can be changed from the shape editor GUI. Existing shapes can be - browsed and edited from the same category. -- *Volumes.* The category allows the creation of a new volume having a - given name, shape and medium. For creating a volume assembly only - the name is relevant. Existing volumes can be browsed or edited from - this category. -- *Materials.* Allows creation of new materials/mixtures or editing - existing ones. -- *Media.* The same for creation/editing of tracking media (materials - having a set of properties related to tracking) -- *Matrices.* Allows creation of translations, rotations or combined - transformations. Existing matrices can also be browser/edited. - -### Editing Existing Objects - -For editing an existing object from one of the categories described -above, the interface imposes first a selection among all objects of the -corresponding type stored in the geometry. This can be done by clicking -the button next to the blue label *Select \*. The dialog -interfaces are generally different for different types of objects. The -volume selection dialog offers the possibility to select either a volume -already connected to the geometry hierarchy or non-connected ones. -Selection for shapes and matrices is split into categories represented -by top-level list tree items for: boxes, tubes, translations, rotations, -etc. - -![Selection dialogs for different TGeo objects](pictures/030001EF.png) - -Once a selection is made and the dialog is closed, the selected item -name will appear in the corresponding label and the button Edit will -start the object editor in a transient frame. Closing these transient -frames will not delete, but just hide existing opened editors for later -reuse. Their lifetime is determined by the canvas to which the manager -editor is attached to, since these will be destroyed together. - -![Editors for shapes, materials, media, matrices](pictures/020001F0.jpg) -![Editors for shapes, materials, media, matrices](pictures/020001F1.jpg) -![Editors for shapes, materials, media, matrices](pictures/020001F2.jpg) -![Editors for shapes, materials, media, matrices](pictures/020001F3.jpg) -![Editors for shapes, materials, media, matrices](pictures/030001F4.png) - -For most editors, the functionalities Apply and Undo are provided. - -For shapes, changing any of the shape parameters will activate the -"*Apply*" button only if the check button "*Delayed draw*" is checked, -otherwise the changes are immediately applied. Once the apply button is -pressed, the changes are applied to the edited shape and drawn. The -"*Undo*" button becomes active after the first modification has been -applied. It allows restoring the initial parameters of the shape. - -NOTE: In this version the "*Undo*" does not allow restoring an -intermediate state of the parameters that was applied - it will always -restore the parameters at the moment the shape was edited. - -All material properties changes are undoable. The mixture editor -currently allows adding elements one by one in the mixture composition. -This can be done either by element weight fraction or by number of -atoms. Once an element was added using one method the other method is not -selectable anymore. Summing component fractions up to 1 in the final -mixture is the user responsibility. Adding materials as components of a -mixture is not supported in this version. - -The elements that were added to the mixture appear in the bottom of the -mixture editor. The operations performed on mixture are not undoable. - -### Creation of New Objects - -As described above, all geometry object creators are accessible within -the geometry manager editor frame. Generally, if the new object that -needs to be created does not depend on other objects, it will be built -with a set of default parameters. This is the case for all shapes -(except composite shapes) and matrices. For all the other objects the -interface forces the selection of components before creating the object. - -### Editing Volumes - -Volumes are hierarchical components in the geometry, therefore their -editor is more complex. It provides the following functionalities: - -- *General*. This category allows changing the name of the volume and - selecting other shape or medium among existing ones. - -- *Daughters*. The category allows removing existing daughter nodes or - adding new ones. The button "*Position*" allows editing the - positioning matrix of a given node. - -![Setting volume properties and modifying volume hierarchy](pictures/020001F5.jpg) -![Setting volume properties and modifying volume hierarchy](pictures/020001F6.jpg) - -- *Visualization*. This category allows changing the visibility of the - edited volume or for its daughters, as well as other visualization - settings. The radio button "*All*" allows viewing all volumes down - to the selected depth. "*Leaves*" will draw only the deepest nodes - that have the selected depth or lower level ones that have no - daughters inside. "*Only*" will allow drawing only the edited - volume. The check button "*Raytrace*" will just draw the current - selection in solid mode using the ray-tracing algorithm provided by - TGeo. - -![Volume visualisation settings and division interface for volumes](pictures/020001F7.jpg) -![Volume visualisation settings and division interface for volumes](pictures/020001F8.jpg) - -- *Division*. Allows dividing the edited volume according a given - pattern. The division axes that are allowed are presented in a - radio-button group. The number entries labeled "*From*", "*Step*" - and "*Nslices*" correspond to the divisioning parameters on the - selected axis. The range of the division is between `start` and - `start+ndiv*step` values and its validity is checked upon changing - one of the values. - -NOTE: When changing a value in a number entry by typing a number, press -ENTER at the end to validate. This applies for taking into account and -validation of any number change in the geometry editors. - -### How to Create a Valid Geometry with Geometry Editors - -1. Create a new geometry manager and start the editor as described at -the beginning. - -2. Create at least one material from the "*Materials*" shutter item -category. Generally, for creating objects, the interface is always in -the **`TGeoManagerEditor`** in different categories - one should just -provide a name and requested parameters. - -3. Create a shape that will be used for the top volume within the -"*Shapes*" category. For the moment, the shapes that have editors are -Box, Para, Trd1, Trd2, Tube, Tube segment, Cone, Cone segment, Hype, -Pcon, Torus and Sphere. - -4. Create a medium from one of the existing materials from the -"*Medium*" category. You will notice that some categories as "*Volume*" -and "*Medium*" are inactive at the beginning because at that time there -is no material yet (for making a medium) and no shape (for making a -volume). These categories are dynamically activated once all the -required components are defined. - -5. Create a volume from the "*Volumes*" category. You will notice that -contrary to the other editors, the volume editor is opened in a tab, not -transient - this is because it is more complex. - -6. Go back to "*General*" category and select the newly created volume -as the top one (you can do it also from the volume category). This is -just for starting. To create some hierarchy, one has to create several -other volumes and the matrices to position them. Once this is done, use -the volume editor interface to: - - add/remove daughters, change shape, edit position of daughters - - change visualization settings - - divide the volume (only if there are no daughters yet) - -7. Close the geometry from the "*General*" category. diff --git a/documentation/users-guide/GettingStarted.md b/documentation/users-guide/GettingStarted.md deleted file mode 100644 index 22a83111cbb93..0000000000000 --- a/documentation/users-guide/GettingStarted.md +++ /dev/null @@ -1,1318 +0,0 @@ -# Getting Started - - -We begin by showing you how to use ROOT interactively. There are two -examples to click through and learn how to use the GUI. We continue by -using the command line, and explaining the coding conventions, global -variables and the environment setup. If you have not installed ROOT, -you can do so by following the instructions in the appendix, or on the -ROOT web site: - -## Setting the Environment Variables - - -Before you can run ROOT you need to set the environment variable -`ROOTSYS` and change your path to include `root/bin` and library path -variables to include `root/lib`. Please note: the syntax is for -`bash`, if you are running `tcsh` you will have to use `setenv` -instead of `export`. - -1. Define the variable \$ROOTSYS to the directory where you unpacked -the ROOT: - -``` -$ export ROOTSYS=$HOME/root -``` - -2. Add ROOTSYS/bin to your PATH: - -``` -$ export PATH=$PATH:$ROOTSYS/bin -``` - -3. Setting the Library Path - -On HP-UX, before executing the interactive module, you must set the -library path: - -``` -$ export SHLIB_PATH=$SHLIB_PATH:$ROOTSYS/lib -``` - -On AIX, before executing the interactive module, you must set the -library path: - -``` -$ [ -z "$LIBPATH" ] && export LIBPATH=/lib:/usr/lib -$ export LIBPATH=$LIBPATH:$ROOTSYS/lib -``` - -On Linux, Solaris, Alpha OSF and SGI, before executing the interactive -module, you must set the library path: - -``` -$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib -``` - -On Solaris, in case your LD\_LIBRARY\_PATH is empty, you should set -it: - -``` -$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib:/usr/dt/lib -``` - -If you use the `afs` version you should set (*vers* = version number, -*arch* = architecture): - -``` -$ export ROOTSYS=/afs/cern.ch/sw/lcg/external/root/vers/arch/root -``` - -If ROOT was installed in `$HOME/myroot` directory on a local machine, -one can do: - -``` -cd $HOME/myroot -. bin/thisroot.sh // or source bin/thisroot.sh -``` - -The new `$ROOTSYS/bin/thisroot.[c]sh` scripts will set correctly the -`ROOTSYS`, `LD_LIBRARY_PATH` or other paths depending on the platform -and the `MANPATH`. To run the program just type: `root`. - -## Start and Quit a ROOT Session - - -``` -$ root - ------------------------------------------------------------------------- - | Welcome to ROOT 6.10/01 http://root.cern.ch | - | (c) 1995-2017, The ROOT Team | - | Built for macosx64 | - | From heads/v6-10-00-patches@v6-10-00-25-g9f78c3a, Jul 03 2017, 11:39:44 | - | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' | - ------------------------------------------------------------------------- - -root [0] -``` - -To start ROOT you can type `root` at the system prompt. This starts up -Cling, the ROOT command line C/C++ interpreter, and it gives you the -ROOT prompt (`root[0]`). - -It is possible to launch ROOT with some command line options, as shown -below: - -``` -% root -? -Usage: root [-l] [-b] [-n] [-q] [dir] [[file:]data.root] - [file1.C ... fileN.C] -Options: - -b : run in batch mode without graphics - -n : do not execute logon and logoff macros as specified in .rootrc - -q : exit after processing command line macro files - -l : do not show splash screen - -x : exit on exception - dir : if dir is a valid directory cd to it before executing - - -? : print usage - -h : print usage - --help : print usage - -config : print ./configure options -``` - -- -b ROOT session runs in batch mode, without graphics display. This - mode is useful in case one does not want to set the DISPLAY or - cannot do it for some reason. - -- -n usually, launching a ROOT session will execute a logon script - and quitting will execute a logoff script. This option prevents - the execution of these two scripts. - -- it is also possible to execute a script without entering a ROOT - session. One simply adds the name of the script(s) after the ROOT - command. Be warned: after finishing the execution of the script, - ROOT will normally enter a new session. - -- -q process command line script files and exit. - -For example if you would like to run a script `myMacro.C` in the -background, redirect the output into a file `myMacro.log`, and exit -after the script execution, use the following syntax: - -``` -root -b -q myMacro.C > myMacro.log -``` - -If you need to pass a parameter to the script use: - -``` -root -b -q 'myMacro.C(3)' > myMacro.log -``` - -Be mindful of the quotes, i.e. if you need to pass a string as a -parameter, the syntax is: - -``` -root -b -q 'myMacro.C("text")' > myMacro.log -``` - -You can build a shared library with ACLiC and then use this shared -library on the command line for a quicker execution (i.e. the compiled -speed rather than the interpreted speed). See also "Cling the C++ -Interpreter". - -``` -root -b -q myMacro.so > myMacro.log -``` - -ROOT has a powerful C/C++ interpreter giving you access to all available -ROOT classes, global variables, and functions via the command line. By -typing C++ statements at the prompt, you can create objects, call -functions, execute scripts, etc. For example: - -``` {.cpp} -root[] 1+sqrt(9) -(const double)4.00000000000000000e+00 -root[] for (int i = 0; i<4; i++) cout << "Hello" << i << endl -Hello 0 -Hello 1 -Hello 2 -Hello 3 -root[] .q -``` - -To exit the ROOT session, type `.q`. - -``` {.cpp} -root[] .q -``` - -## Using the GUI - - -The basic whiteboard on which an object is drawn in ROOT is called a -canvas (defined by the class **`TCanvas`**). Every object in the -canvas is a graphical object in the sense that you can grab it, resize -it, and change some characteristics using the mouse. The canvas area -can be divided in several sub areas, so-called pads -(the class **`TPad`**). A pad is a canvas sub area that can contain -other pads or graphical objects. At any one time, just one pad is the -so-called active pad. Any object at the moment of drawing will be -drawn in the active pad. The obvious question is: what is the relation -between a canvas and a pad? In fact, a canvas is a pad that spans -through an entire window. This is nothing else than the notion of -inheritance. The **`TPad`** class is the parent of the **`TCanvas`** -class. In ROOT, most objects derive from a base class **`TObject`**. -This class has a virtual method `Draw()` such as all objects are -supposed to be able to be "drawn". If several canvases are defined, -there is only one active at a time. One draws an object in the active -canvas by using the statement: - -``` {.cpp} -object.Draw() -``` - -This instructs the object "`object`" to draw itself. If no canvas is -opened, a default one (named "`c1`") is created. In the next example, -the first statement defines a function and the second one draws it. A -default canvas is created since there was no opened one. You should -see the picture as shown in the next figure. - -``` {.cpp} -root[] TF1 f1("func1","sin(x)/x",0,10) -root[] f1.Draw() -: created default TCanvas with name c1 -``` - -![A canvas with drawing](pictures/0300000A.png) - -The following components comprise the canvas window: - -- Menu bar - contains main menus for global operations with files, - print, clear canvas, inspect, etc. - -- Tool bar - has buttons for global and drawing operations; such as - arrow, ellipse, latex, pad, etc. - -- Canvas - an area to draw objects. - -- Status bar - displays descriptive messages about the selected - object. - -- Editor frame - responds dynamically and presents the user - interface according to the selected object in the canvas. - -### Main Menus and Toolbar - - -At the top of the canvas window are File, Edit, View, Options, -Inspect, Classes and Help menus. - -#### File Menu - - -- *New Canvas*: creates a new canvas window in the current ROOT - session. - -- *Open...*: popup a dialog to open a file. - -- *Close Canvas*: close the canvas window. - -- *Save*: save the drawing of the current canvas in a format - selectable from the submenu. The current canvas name is used as a - file name for various formats such as PostScript, GIF, JPEG, C - macro file, root file. - -- *Save As...*: popup a dialog for saving the current canvas drawing - in a new filename. - -- *Print*: popup a dialog to print the current canvas drawing - -- *Quit ROOT*: exit the ROOT session - -![](pictures/0300000B.png) - - -#### Edit Menu - -There is only one active menu entry in the Edit menu. The others menu -entries will be implemented and will become active in the near future. - -- *Clear:* delete all objects in the canvas - or in the selected pad according to the selected entry in the - submenu. - -#### View Menu - - -- *Editor*: toggles the view of the editor. If it is selected - activates and shows up the editor on the left side of the canvas - window. According to the selected object, the editor loads the - corresponding user interface for easy change of the object's - attributes. - -- *Toolbar*: toggles the view of the toolbar. If it is selected - activates and shows up the toolbar. It contains buttons for easy - and fast access to most frequently used commands and for graphics - primitive drawing. Tool tips are provided for helping users. - -- *Status Bar*: toggles the view of the status bar. If it is - selected, the status bar below the canvas window shows up. There - the identification of the objects is displayed when moving the - mouse (such as the object's name, the object's type, its - coordinates, etc.). - -- *Colors*: creates a new canvas showing the color palette. - -- *Markers*: creates a new canvas showing the various marker styles. - -- *Iconify*: create the canvas window icon, does not close the - canvas - -- *View With...*: If the last selected pad contains a 3-d structure, - a new canvas is created with a 3-D picture according to the - selection made from the cascaded menu: X3D or OpenGL. The 3-D - image can be interactively rotated, zoomed in wire-frame, solid, - hidden line or stereo mode. - -![](pictures/0300000C.png) - -#### Options Menu - - -- *Auto Resize Canvas*: turns auto-resize of the canvas *on/off*: - - - *on* - the canvas fits to the window when changing the window - size; - - *off* - the canvas stays fixed when changing the window size. - -- *Resize Canvas*: resizes and fits the canvas to the window size. - -- *Move Opaque*: if selected, graphics objects are moved in opaque - mode; otherwise, only the outline of objects is drawn when moving - them. The option opaque produces the best effect but it requires a - reasonably fast workstation or response time. - -- *Resize Opaque*: if selected, graphics objects are resized in - opaque mode; otherwise, only the outline of objects is drawn when - resizing them. - -- *Interrupt*: interrupts the current drawing process. - -- *Refresh*: redraws the canvas contents. - -- *Pad Auto Exec*: executes the list of **`TExecs`** in the current - pad. - -- *Statistics*: toggles the display of the histogram statistics box. - -- *Histogram Title*: toggles the display of the histogram title. - -- *Fit Parameters*: toggles the display of the histogram or graph - fit parameters. - -- *Can Edit Histogram*: enables/disables the possibility to edit - histogram bin contents. - -![](pictures/0300000D.png) - -#### Inspect Menu - - -- *ROOT*: inspects the top-level ***`gROOT`*** object (in a new - canvas). - -- *Start Browser*: starts a new object browser (in a separate - window). - -- *GUI Builder*: starts the GUI builder application (in a separate - window). - -![](pictures/0300000E.png) - - -#### Help Menu - - -- *Canvas:* help on canvas as a whiteboard area for drawing. - -- *Menus*: help on canvas menus. - -- *Graphics Editor*: help on primitives' drawing and objects' - editor. - -- *Browser*: help on the ROOT objects' and files' browser. - -- *Objects*: help on DrawClass, Inspect and Dump context menu items. - -- *PostScript*: help on how to print a canvas to a PostScript file - format. - -- *About ROOT*: pops up the ROOT Logo with the version number. - -![](pictures/0300000F.png) - - -#### Classes Menu - -- *Classes*: starts the ClassTree viewer that draws inheritance tree - for a list of classes. - - -#### Toolbar - -The following menu shortcuts and utilities are available from the -toolbar: - -![](pictures/03000010.png) Create a new canvas window. - -![](pictures/03000011.png) Popup the Open File dialog. - -![](pictures/03000012.png) Popup the Save As... dialog. - -![](pictures/03000013.png) Popup the Print dialog. - -![](pictures/03000014.png) Interrupts the current drawing process. - -![](pictures/03000015.png) Redraw the canvas. - -![](pictures/03000016.png) Inspect the ***`gROOT`*** object. - -![](pictures/03000017.png) Create a new objects' browser. - -You can create the following graphical objects using the toolbar -buttons for primitive drawing. Tool tips are provided for helping -your choice. - -![](pictures/03000018.png) **An Arc or circle**: Click on the center -of the arc, and then move the mouse. A rubber band circle is shown. -Click again with the left button to freeze the arc. - -![](pictures/03000019.png) **A Line**: Click with the left button at -the point where you want to start the line, then move the mouse and -click again with the left button to freeze the line. - -![](pictures/0300001A.png) **An Arrow:**Click with the left button at -the point where you want to start the arrow, then move the mouse and -click again with the left button to freeze the arrow. - -![](pictures/0300001B.png) **A Diamond**: Click with the left button -and freeze again with the left button. The editor draws a rubber band -box to suggest the outline of the diamond. - -![](pictures/0300001C.png) **An Ellipse**: Proceed like for an arc. -You can grow/shrink the ellipse by pointing to the sensitive points. -They are highlighted. You can move the ellipse by clicking on the -ellipse, but not on the sensitive points. If, with the ellipse context -menu, you have selected a fill area color, you can move a -filled-ellipse by pointing inside the ellipse and dragging it to its -new position. - -![](pictures/0300001D.png) **A Pad**: Click with the left button and -freeze again with the left button. The editor draws a rubber band box -to suggest the outline of the pad. - -![](pictures/0300001E.png) **A PaveLabel**: Proceed like for a pad. -Type the text of label and finish with a carriage return. The text -will appear in the box. - -![](pictures/0300001F.png) **A Pave Text**: Proceed like for a pad. -You can then click on the **`TPaveText`** object with the right mouse -button and select the option `InsertText`. - -![](pictures/03000020.png) **Paves Text**: Proceed like for a -**`TPaveText`**. - -![](pictures/03000021.png) **A Poly Line**: Click with the left button -for the first point, move the moose, click again with the left button -for a new point. Close the poly-line with a double click. To edit one -vertex point, pick it with the left button and drag to the new point -position. - -![](pictures/03000022.png) **A Curly Line**: Proceed as for the arrow -or line. Once done, click with the third button to change the -characteristics of the curly line, like transform it to wave, change -the wavelength, etc. - -![](pictures/03000023.png) **A Curly Arc**: Proceed like for an -ellipse. The first click is located at the position of the center, the -second click at the position of the arc beginning. Once done, one -obtains a curly ellipse, for which one can click with the third button -to change the characteristics, like transform it to wavy, change the -wavelength, set the minimum and maximum angle to make an arc that is -not closed, etc. - -![](pictures/03000024.png) **A Text/Latex string**: Click with the -left button where you want to draw the text and then type in the text -terminated by carriage return. All **`TLatex`** expressions are valid. -To move the text or formula, point on it keeping the left mouse button -pressed and drag the text to its new position. You can grow/shrink the -text if you position the mouse to the first top-third part of the -string, then move the mouse up or down to grow or shrink the text -respectively. If you position the mouse near the bottom-end of the -text, you can rotate it. - -![](pictures/03000025.png) **A Marker**: Click with the left button -where to place the marker. The marker can be modified by using the -method `SetMarkerStyle()` of **`TSystem`**. - -![](pictures/03000026.png) **A Graphical Cut**: Click with the left -button on each point of a polygon delimiting the selected area. Close -the cut by double clicking on the last point. A **`TCutG`** object is -created. It can be used as a selection for a **`TTree`**`::Draw`. You -can get a pointer to this object with: - -``` {.cpp} -TCutG cut = (TCutG*)gPad->GetPrimitive("CUTG") -``` - -Once you are happy with your picture, you can select the -`Save as canvas.C` item in the canvas File menu. This will -automatically generate a script with the C++ statements corresponding -to the picture. This facility also works if you have other objects not -drawn with the graphics editor (histograms for example). - -### The Editor Frame - - -The ROOT graphics editor loads the corresponding object editor -`objEditor` according to the selected object `obj` in the canvas -respecting the class inheritance. An object in the canvas is selected -after the left mouse click on it. For example, if the selected object -is **`TAxis`**, the **`TAxisEditor`** will shows up in the editor -frame giving the possibility for changing different axis attributes. -The graphics editor can be: - -Embedded - connected only with the canvas in the application window -that appears on the left of the canvas window after been activated via -View menu / Editor. It appears on the left side if the canvas window -allowing users to edit the attributes of the selected object via -provided user interface. The name of the selected object is displayed -on the top of the editor frame in red color. If the user interface -needs more space then the height of the canvas window, a vertical -scroll bar appears for easer navigation. - -![](pictures/03000027.png) - -Global - has own application window and can be connected to any -created canvas in a ROOT session. It can be activated via the context -menu entries for setting line, fill, text and marker attributes for -backward compatibility, but there will be a unique entry in the near -future. - -![](pictures/03000028.png) - -The user interface for the following classes is available since ROOT -v.4.04: **`TAttLine`**, **`TAttFill`**, **`TAttMarker`**, -**`TAttText`**, **`TArrow`**, **`TAxis`**, **`TCurlyArc`**, -**`TCurlyLine`**, **`TFrame`**, **`TH1`**, **`TH2`**, **`TGraph`**, -**`TPad`**, **`TCanvas`**, **`TPaveStats`**. For more details, see -"The Graphics Editor", "The User Interface for Histograms", "The User -Interface for Graphs". - -### Classes, Methods and Constructors - - -Object oriented programming introduces objects, which have data -members and methods. The next line creates an object named `f1` of the -class **`TF1`** that is a one-dimensional function. The type of an -object is called a class. The object itself is called an instance of a -class. When a method builds an object, it is called a constructor. - -``` {.cpp} -TF1 f1("func1","sin(x)/x",0,10) -``` - -In our constructor the function sin(x)/x is defined for use, and 0 and -10 are the limits. The first parameter, `func1` is the name of the -object `f1`. Most objects in ROOT have a name. ROOT maintains a list -of objects that can be searched to find any object by its given name -(in our example `func1`). - -The syntax to call an object's method, or if one prefers, to make an -object to do something is: - -``` {.cpp} -object.method_name(parameters) -``` - -The dot can be replaced by "`->`" if `object` is a pointer. In -compiled code, the dot MUST be replaced by a "`->`" if object is a -pointer. - -``` {.cpp} -object_ptr->method_name(parameters) -``` - -So now, we understand the two lines of code that allowed us to draw -our function. `f1.Draw()` stands for "call the method `Draw()` -associated with the object `f1` of the class **`TF1`**". Other methods -can be applied to the object `f1` of the class **`TF1`**. For example, -the evaluating and calculating the derivative and the integral are -what one would expect from a function. - -``` {.cpp} -root[] f1.Eval(3) -(Double_t)4.70400026866224020e-02 -root[] f1.Derivative(3) -(Double_t)(-3.45675056671992330e-01) -root[] f1.Integral(0,3) -(Double_t)1.84865252799946810e+00 -root[] f1.Draw() -``` - -By default the method `TF1::Paint()`, that draws the function, -computes 100 equidistant points to draw it. The number of points can -be set to a higher value with: - -``` {.cpp} -root[] f1.SetNpx(2000); -``` - -Note that while the ROOT framework is an object-oriented framework, -this does not prevent the user from calling plain functions. - -### User Interaction - - -Now we will look at some interactive capabilities. Try to draw the -function `sin(x)/x` again. Every object in a window (which is called a -canvas) is, in fact, a graphical object in the sense that you can grab -it, resize it, and change its characteristics with a mouse click. For -example, bring the cursor over the x-axis. The cursor changes to a -hand with a pointing finger when it is over the axis. Now, left click -and drag the mouse along the axis to the right. You have a very simple -zoom. - -When you move the mouse over any object, you can get access to -selected methods by pressing the right mouse button and obtaining a -context menu. If you try this on the function **`TF1`**, you will get -a menu showing available methods. The other objects on this canvas are -the title, a **`TPaveText`** object`;` the x and y-axis, **`TAxis`** -objects, the frame, a **`TFrame`** object, and the canvas a -**`TCanvas `** object. Try clicking on these and observe the context -menu with their methods. - -![A context menu](pictures/0300002A.png) - -For example try selecting the `SetRange()` method and putting `-10`, -`10` in the dialog box fields. This is equivalent to executing -`f1.SetRange(-10,10)` from the command line, followed by `f1.Draw()`. -Here are some other options you can try. - -Once the picture suits your wishes, you may want to see the code you -should put in a script to obtain the same result. To do that, choose -Save / `canvas.C` entry of the File menu. This will generate a script -showing the options set in the current canvas. Notice that you can -also save the picture into various file formats such as PostScript, -GIF, etc. Another interesting possibility is to save your canvas into -the native ROOT format (`.root `file). This will enable you to open it -again and to change whatever you like. All objects associated to the -canvas (histograms, graphs) are saved at the same time. - -### Building a Multi-pad Canvas - - -Let us now try to build a canvas with several pads. - -``` {.cpp} -root[] TCanvas *MyC = new TCanvas("MyC","Test canvas",1) -root[] MyC->Divide(2,2) -``` - -Once again, we call the constructor of a class, this time the class -**`TCanvas`**. The difference between this and the previous -constructor call (**`TF1`**) is that here we are creating a pointer to -an object. Next, we call the method `Divide()` of the **`TCanvas`** -class (that is `TCanvas::Divide())`, which divides the canvas into -four zones and sets up a pad in each of them. We set the first pad as -the active one and than draw the function` f1 `there. - -``` {.cpp} -root[] MyC->cd(1) -root[] f1->Draw() -``` - -All objects will be drawn in that pad because it is the active one. -The ways for changing the active pad are: - -- Click the middle mouse button on a pad will set this pad as the - active one. - -- Use the method `TCanvas::cd()` with the pad number, as was done in - the example above: - -``` {.cpp} -root[] MyC->cd(3) -``` - -Pads are numbered from left to right and from top to bottom. Each new -pad created by `TCanvas::Divide()` has a name, which is the name of -the canvas followed by \_1, \_2, etc. To apply the method `cd()` to -the third pad, you would write: - -``` {.cpp} -root[] MyC_3->cd() -``` - -- Third pad will be selected since you called `TPad::cd()` for the - object `MyC_3`. ROOT will find the pad that was named` MyC_3 `when - you typed it on the command line (see ROOT/Cling Extensions to - C++). - -### Saving the Canvas - - -![The SaveAs... dialog](pictures/0300002B.png) - -Using the File menu / Save cascade menu users can save the canvas as -one of the files from the list. Please note that saving the canvas -this way will overwrite the file with the same name without a warning. - -All supported file types can be saved via File menu / SaveAs... This -dialog gives a choice to show or suppress the confirmation message for -overwriting an existing file. - -If the Overwrite check box is not selected, a message dialog appears -asking the user to overwrite the file (Yes/No). The user choice is -saved for the next time the Save As... dialog shows up. - -### Printing the Canvas - - -The Print command in the canvas File menu pops-up a print dialog where -the user can specify a preferred print command and the printer name. - -![](pictures/0300002D.png) - -Both print parameters can be set via the new Print.Command and -Print.Printer rootrc resources as follows: - -``` -# Printer settings. -WinNT.*.Print.Command: AcroRd32.exe -Unix.*.Print.Command: xprint -P%p %f -Print.Printer: 32-rb205-hp -Print.Directory: . -``` - -If the `%p` and `%f` are specified as a part of the print command, -they will be replaced by the specified printer name and the file name. -All other parameters will be kept as they are written. A print button -is available in the canvas toolbar (activated via View menu/Toolbar). - -## The ROOT Command Line - - -We have briefly touched on how to use the command line. There are -different types of commands. - -1. Cling commands start with "`.`" - -``` {.cpp} -root[] .? //this command will list all the Cling commands -root[] .L //load [filename] -root[] .x //load and execute [filename] -``` - -2. SHELL commands start with "`.!`" for example: - -``` {.cpp} -root[] .! ls -``` - -3. C++ commands follow C++ syntax (almost) - -``` {.cpp} -root[] TBrowser *b = new TBrowser() -``` - -### Multi-line Commands - - -You can use the command line to execute multi-line commands. To begin -a multi-line command you must type a single left curly bracket `{`, -and to end it you must type a single right curly bracket `}`. -For example: - -``` {.cpp} -root[] { -end with '}'> Int_t j = 0; -end with '}'> for (Int_t i = 0; i < 3; i++) -end with '}'> { -end with '}'> j= j + i; -end with '}'> cout << "i = " << i << ", j = " << j << endl; -end with '}'> } -end with '}'> } -i = 0, j = 0 -i = 1, j = 1 -i = 2, j = 3 -``` - -It is more convenient to edit a script than the command line, and if -your multi line commands are getting unmanageable, you may want to -start with a script instead. - -### Cling Extensions - - -We should say that some things are not standard C++. The Cling -interpreter has several extensions. See "ROOT/Cling Extensions to C++". - -### Helpful Hints for Command Line Typing - - -The interpreter knows all the classes, functions, variables, and user -defined types. This enables ROOT to help users to complete the command -line. For example, if we do not know anything about the **`TLine`** -class, the Tab feature helps us to get a list of all classes starting -with **`TL`**(where `` means type the Tab key). - -``` {.cpp} -root[] l = new TLi -TList -TListIter -TLink -TLine -TLimitDataSource -TLimit -``` - -To list the different constructors and parameters for **`TLine`** use -the `` key as follows: - -``` {.cpp} -root[] l = new TLine( -TLine TLine() -TLine TLine(Double_t x1,Double_t y1,Double_t x2,Double_t y2) -TLine TLine(const TLine& line) -``` - -### Regular Expression - - -The meta-characters below can be used in a regular expression: - -- '`^`' start-of-line anchor - -- '`$`' end-of-line anchor - -- '`.`' matches any character - -- '`[`' start a character class - -- '`]`'end a character class - -- '`^`'negates character class if first character - -- '`*`'`Kleene` closure (matches 0 or more) - -- '`+`'Positive closure (1 or more) - -- '`?`' Optional closure (0 or 1) - -When using wildcards the regular expression is assumed to be preceded -by a '`^`' (BOL) and terminated by '`$`' (EOL). All '`*`' (closures) -are assumed to be preceded by a '`.`', i.e. any character, except -slash \_`/_`. Its special treatment allows the easy matching of -pathnames. For example, `_*.root_` will match `_aap.root_`, but not -`_pipo/aap.root_`. - -The escape characters are: - -- `\` backslash - -- `b` backspace - -- `f` form feed - -- `n` new line - -- `r` carriage return - -- `s` space - -- `t` tab - -- `e` ASCII ESC character ('033') - -- `DDD` number formed of 1-3 octal digits - -- `xDD` number formed of 1-2 hex digits - -- `^C` C = any letter. Control code - -The class **`TRegexp`** can be used to create a regular expression -from an input string. If `wildcard` is true then the input string -contains a wildcard expression. - -``` {.cpp} -TRegexp(const char *re, Bool_t wildcard) -``` - -Regular expression and wildcards can be easily used in methods like: - -``` {.cpp} -Ssiz_t Index(const TString& string,Ssiz_t* len,Ssiz_t i) const -``` - -The method finds the first occurrence of the regular expression in the -`string` and returns its position. - -## Conventions - - -In this paragraph, we will explain some of the conventions used in -ROOT source and examples. - -### Coding Conventions - - -From the first days of ROOT development, it was decided to use a set -of coding conventions. This allows a consistency throughout the source -code. Learning these will help you identify what type of information -you are dealing with and enable you to understand the code better and -quicker. Of course, you can use whatever convention you want but if -you are going to submit some code for inclusion into the ROOT sources, -you will need to use these. - -These are the coding conventions: - -- Classes begin with **`T`**: **`TLine`**, **`TTree`** - -- Non-class types end with **`_t`**: `Int_t` - -- Data members begin with **`f`**: `fTree` - -- Member functions begin with a capital: `Loop()` - -- Constants begin with **`k`**: `kInitialSize`, `kRed ` - -- Global variables begin with **`g`**: ***`gEnv`*** - -- Static data members begin with **`fg`**: `fgTokenClient ` - -- Enumeration types begin with **`E`**: `EColorLevel` - -- Locals and parameters begin with a lower case: `nbytes` - -- Getters and setters begin with **`Get`** and **`Set`**: - `SetLast`(), `GetFirst`() - -### Machine Independent Types - - -Different machines may have different lengths for the same type. The -most famous example is the `int` type. It may be 16 bits on some old -machines and 32 bits on some newer ones. To ensure the size of your -variables, use these pre defined types in ROOT: - -- **`Char_t`** Signed Character 1 byte - -- **`UChar_t`** Unsigned Character 1 byte - -- **`Short_t`** Signed Short integer 2 bytes - -- **`UShort_t`** Unsigned Short integer 2 bytes - -- **`Int_t`** Signed integer 4 bytes - -- **`UInt_t `**Unsigned integer 4 bytes - -- **`Long64_t`** Portable signed long integer 8 bytes - -- **`ULong64_t`** Portable unsigned long integer 8 bytes - -- **`Float_t`** Float 4 bytes - -- **`Double_t`** Float 8 bytes - -- **`Double32_t`** Double 8 bytes in memory, written as a Float 4 - bytes - -- **`Bool_t`** Boolean (0=false, 1=true) - -If you do not want to save a variable on disk, you can use `int` or -`Int_t`, the result will be the same and the interpreter or the -compiler will treat them in exactly the same way. - -### TObject - - -In ROOT, almost all classes inherit from a common base class called -**`TObject`**. This kind of architecture is also used in the Java -language. The **`TObject`** class provides default behavior and -protocol for all objects in the ROOT system. The main advantage of -this approach is that it enforces the common behavior of the derived -classes and consequently it ensures the consistency of the whole -system. See "The Role of TObject". - -**`TObject`** provides protocol, i.e. (abstract) member functions, -for: - -- Object I/O (`Read()`, `Write())` - -- Error handling (`Warning()`, `Error()`, `SysError()`, `Fatal())` - -- Sorting (`IsSortable()`, `Compare()`, `IsEqual()`, `Hash())` - -- Inspection (`Dump()`, `Inspect()`) - -- Printing (`Print())` - -- Drawing (`Draw()`, `Paint()`, `ExecuteEvent())` - -- Bit handling (`SetBit()`, `TestBit()`) - -- Memory allocation (operator` new and delete`, `IsOnHeap())` - -- Access to meta information (`IsA()`, `InheritsFrom())` - -- Object browsing (`Browse()`, `IsFolder())` - -## Global Variables - - -ROOT has a set of global variables that apply to the session. For -example, -***`gDirectory`*** always holds the current directory, and -***`gStyle`*** holds the current style. - -All global variables begin with "*g*" followed by a capital letter. - - - -### gROOT - - -The single instance of **`TROOT`** is accessible via the global -***`gROOT`*** and holds information relative to the current session. -By using the ***`gROOT`*** pointer, you get the access to every object -created in a ROOT program. The **`TROOT`** object has several lists -pointing to the main ROOT objects. During a ROOT session, the -***`gROOT`*** keeps a series of collections to manage objects. They -can be accessed via ***`gROOT`***`::GetListOf...` methods. - -``` {.cpp} -gROOT->GetListOfClasses() -gROOT->GetListOfColors() -gROOT->GetListOfTypes() -gROOT->GetListOfGlobals() -gROOT->GetListOfGlobalFunctions() -gROOT->GetListOfFiles() -gROOT->GetListOfMappedFiles() -gROOT->GetListOfSockets() -gROOT->GetListOfCanvases() -gROOT->GetListOfStyles() -gROOT->GetListOfFunctions() -gROOT->GetListOfSpecials() -gROOT->GetListOfGeometries() -gROOT->GetListOfBrowsers() -gROOT->GetListOfMessageHandlers() -``` - -These methods return a **`TSeqCollection`**, meaning a collection of -objects, and they can be used to do list operations such as finding an -object, or traversing the list and calling a method for each of the -members. See the **`TCollection`** class description for the full set -of methods supported for a collection. For example, to find a canvas -called `c1 `you can do`:` - -``` {.cpp} -root[] gROOT->GetListOfCanvases()->FindObject("c1") -``` - -This returns a pointer to a **`TObject`**, and before you can use it -as a canvas you need to cast it to a **`TCanvas*`.** - -### gFile - - -***`gFile`*** is the pointer to the current opened file in the ROOT -session. - -### gDirectory - - -***`gDirectory`*** is a pointer to the current directory. The concept -and role of a directory is explained in the chapter "Input/Output". - -### gPad - - -A graphic object is always drawn on the active pad. It is convenient -to access the active pad, no matter what it is. For that, we have -***`gPad`*** that is always pointing to the active pad. For example, -if you want to change the fill color of the active pad to blue, but -you do not know its name, you can use ***`gPad`***. - -``` {.cpp} -root[] gPad->SetFillColor(38) -``` - -To get the list of colors, if you have an open canvas, click in the -"View" menu, selecting the "Colors" entry. - -### gRandom - - -***`gRandom`*** is a pointer to the current random number generator. -By default, it points to a **`TRandom3`** object, based on the -"Mersenne-Twister" generator. This generator is very fast and has very -good random proprieties (a very long period of 10^600^). Setting the -seed to 0 implies that the seed will be uniquely generated using the -**`TUUID`**. Any other value will be used as a constant. The following -basic random distributions are provided: `Rndm()` or -`Uniform(min,max)`, `Gaus(mean,sigma)`, `Exp(tau)`, -`BreitWigner(mean,sigma)`, `Landau(mean,sigma)`, `Poisson(mean)`, -`Binomial(ntot,prob)`. You can customize your ROOT session by -replacing the random number generator. -You can delete ***`gRandom `*** and recreate it with your own. For -example: - -``` {.cpp} -root[] delete gRandom; -root[] gRandom = new TRandom2(0); //seed=0 -``` - -**`TRandom2`** is another generator, which is also very fast and uses -only three words for its state. - -### gEnv - - -**`gEnv`** is the global variable (of type **`TEnv`**) with all the -environment settings for the current session. This variable is set by -reading the contents of a `.rootrc` file (or -`$ROOTSYS/etc/system.rootrc`) at the beginning of the root session. -See Environment Setup below for more information. - -## Environment Setup - - -The behavior of a ROOT session can be tailored with the options in the -.`rootrc` file. At start-up, ROOT looks for a .`rootrc` file in the -following order: - -- `./.rootrc` *`//local directory`* - -- `$HOME/.rootrc ` *`//user directory`* - -- `$ROOTSYS/etc/system.rootrc ` *`//global ROOT directory`* - -If more than one `.rootrc` files are found in the search paths above, -the options are merged, with precedence local, user, global. While in -a session, to see current settings, you can do: - -``` {.cpp} -root[] gEnv->Print() -``` - -The `rootrc` file typically looks like: - -``` -# Path used by dynamic loader to find shared libraries -Unix.*.Root.DynamicPath: .:~/rootlibs:$(ROOTSYS)/lib -Unix.*.Root.MacroPath: .:~/rootmacros:$(ROOTSYS)/macros - -# Path where to look for TrueType fonts -Unix.*.Root.UseTTFonts: true -Unix.*.Root.TTFontPath: -... -# Activate memory statistics -Rint.Load: rootalias.C -Rint.Logon: rootlogon.C -Rint.Logoff: rootlogoff.C -... -Rint.Canvas.MoveOpaque: false -Rint.Canvas.HighLightColor: 5 -``` - -The various options are explained in `$ROOTSYS/etc/system.rootrc`. The -`.rootrc` file contents are combined. For example, if the flag to use -true type fonts is set to true in the `system.rootrc` file, you have -to set explicitly it false in your local `.rootrc` file if you do not -want to use true type fonts. Removing the `UseTTFonts `statement in -the local `.rootrc` file will not disable true fonts. The value of the -environment variable `ROOTDEBUG` overrides the value in the `.rootrc` -file at startup. Its value is used to set ***`gDebug`*** and helps for -quick turn on debug mode in **`TROOT`** startup. - -ROOT looks for scripts in the path specified in the `.rootrc` file in -the `Root.Macro.Path` variable. You can expand this path to hold your -own directories. - -### Logon and Logoff Scripts - - -The `rootlogon.C` and `rootlogoff.C` files are scripts loaded and -executed at start-up and shutdown. The `rootalias.C` file is loaded -but not executed. It typically contains small utility functions. For -example, the `rootalias.C` script that comes with the ROOT -distributions (located in `$ROOTSYS/tutorials)` defines the function -`edit(char *file)`. This allows the user to call the editor from the -command line. This particular function will start the VI editor if the -environment variable `EDITOR` is not set. - -``` {.cpp} -root[0] edit("c1.C") -``` - -For more details, see `$ROOTSYS/tutorials/rootalias.C`. - -### History File - - -You can use the up and down arrow at the command line, to access the -previous and next command. The commands are recorded in the history -file `$HOME/.root_hist`. It is a text file, and you can edit, cut, and -paste from it. You can specify the history file in the `system.rootrc` -file, by setting the `Rint.History `option. You can also turn off the -command logging in the `system.rootrc` file with the option: -`Rint.History: -` - -The number of history lines to be kept can be set also in `.rootrc` -by: - -``` -Rint.HistSize: 500 -Rint.HistSave: 400 -``` - -The first value defines the maximum of lines kept; once it is reached -all, the last `HistSave` lines will be removed. One can set `HistSize` -to 0 to disable history line management. There is also implemented an -environment variable called `ROOT_HIST`. By setting -`ROOT_HIST=300:200` the above values can be overriden - the first -value corresponds to `HistSize`, the (optional) second one to -`HistSave`. You can set `ROOT_HIST=0` to disable the history. - -### Tracking Memory Leaks - - -You can track memory usage and detect leaks by monitoring the number -of objects that are created and deleted (see **`TObjectTable`**). To -use this facility, edit the file `$ROOTSYS/etc/system.rootrc` or -`.rootrc` if you have this file and add the two following lines: - -``` -Root.ObjectStat: 1 -``` - -In your code or on the command line you can type the line: - -``` {.cpp} -gObjectTable->Print(); -``` - -This line will print the list of all active classes and the number of -instances for each class. By comparing consecutive print outs, you can -see objects that you forgot to delete. Note that this method cannot -show leaks coming from the allocation of non-objects or classes -unknown to ROOT. - -## Converting from PAW to ROOT - - -The web page at: - gives the -"translation" table of some commonly used PAW commands into ROOT. If -you move the mouse cursor over the picture at: -, you will get -the corresponding ROOT commands as tooltips. - -### Converting HBOOK/PAW Files - - -ROOT has a utility called `h2root` that you can use to convert your -HBOOK/PAW histograms or ntuple files into ROOT files. To use this -program, you type the shell script command: - -``` -h2root -``` - -If you do not specify the second parameter, a file name is -automatically generated for you. If `hbookfile` is of the form -`file.hbook`, then the ROOT file will be called `file.root`. This -utility converts HBOOK histograms into ROOT histograms of the class -**`TH1F`**. HBOOK profile histograms are converted into ROOT profile -histograms (see class **`TProfile`**). HBOOK row-wise and column-wise -ntuples are automatically converted to ROOT Trees. See "Trees". Some -HBOOK column-wise ntuples may not be fully converted if the columns -are an array of fixed dimension (e.g. `var[6]`) or if they are a -multi-dimensional array. - -HBOOK integer identifiers are converted into ROOT named objects by -prefixing the integer identifier with the letter "`h`" if the -identifier is a positive integer and by `"h_"` if it is a negative -integer identifier. In case of row-wise or column-wise ntuples, each -column is converted to a branch of a tree. Note that `h2root` is able -to convert HBOOK files containing several levels of sub-directories. -Once you have converted your file, you can look at it and draw -histograms or process ntuples using the ROOT command line. An example -of session is shown below: - -``` {.cpp} -// this connects the file hbookconverted.root -root[] TFile f("hbookconverted.root"); - -// display histogram named h10 (was HBBOK id 10) -root[] h10.Draw(); - -// display column "var" from ntuple h30 -root[] h30.Draw("var"); -``` - -You can also use the ROOT browser (see **`TBrowser`**) to inspect this -file. - -The chapter on trees explains how to read a tree. ROOT includes a -function **`TTree`**`::MakeClass` to generate automatically the code -for a skeleton analysis function. See "Example Analysis". - -In case one of the ntuple columns has a variable length (e.g. -`px(ntrack)`), `h.Draw("px")` will histogram the `px` column for all -tracks in the same histogram. Use the script quoted above to generate -the skeleton function and create/fill the relevant histogram yourself. diff --git a/documentation/users-guide/Graphics.md b/documentation/users-guide/Graphics.md deleted file mode 100644 index c8c564a737401..0000000000000 --- a/documentation/users-guide/Graphics.md +++ /dev/null @@ -1,4083 +0,0 @@ -# Graphics and the Graphical User Interface - - -Graphical capabilities of ROOT range from 2D objects (lines, polygons, -arrows) to various plots, histograms, and 3D graphical objects. In this -chapter, we are going to focus on principals of graphics and 2D objects. -Plots and histograms are discussed in a chapter of their own. - - -## Drawing Objects - - -In ROOT, most objects derive from a base class **`TObject`**. This class -has a virtual method `Draw()` so all objects are supposed to be able to -be "drawn". The basic whiteboard on which an object is drawn is called a -canvas (defined by the class **`TCanvas`**). If several canvases are -defined, there is only one active at a time. One draws an object in the -active canvas by using the statement: - -``` {.cpp} -object.Draw() -``` - -This instructs the object "`object`" to draw itself. If no canvas is -opened, a default one (named "`c1`") is instantiated and is drawn. - -``` {.cpp} -root[] TLine a(0.1,0.1,0.6,0.6) -root[] a.Draw() -: created default TCanvas with name c1 -``` - -The first statement defines a line and the second one draws it. A -default canvas is drawn since there was no opened one. - -## Interacting with Graphical Objects - - -When an object is drawn, one can interact with it. For example, the line -drawn in the previous paragraph may be moved or transformed. One very -important characteristic of ROOT is that transforming an object on the -screen will also transform it in memory. One actually interacts with the -real object, not with a copy of it on the screen. You can try for -instance to look at the starting X coordinate of the line: - -``` {.cpp} -root[] a.GetX1() -(double)1.000000000e-1 -``` - -`X1` is the `x` value of the starting coordinate given in the definition -above. Now move it interactively by clicking with the left mouse button -in the line's middle and try to do again: - -``` {.cpp} -root[] a.GetX1() -(Double_t)1.31175468483816005e-01 -``` - -You do not obtain the same result as before, the coordinates of '`a`' -have changed. As said, interacting with an object on the screen changes -the object in memory. - -### Moving, Resizing and Modifying Objects - - -Changing the graphic objects attributes can be done with the GUI or -programmatically. First, let's see how it is done in the GUI. - -#### The Left Mouse Button - -As was just seen moving or resizing an object is done with the left -mouse button. The cursor changes its shape to indicate what may be done: - -Point the object or one part of it: ![](pictures/02000095.jpg) -![](pictures/02000096.jpg) - -Rotate: ![](pictures/02000097.jpg) - -Resize (exists also for the other directions): -![](pictures/02000098.jpg) ![](pictures/02000099.jpg) - -Enlarge (used for text): ![](pictures/0200009A.jpg) - -Move: ![](pictures/0200009B.jpg) - -Here are some examples of: - -Moving: ![](pictures/0200009C.jpg) Resizing: ![](pictures/0200009D.jpg) - -Rotating: ![](pictures/0200009E.jpg) ![](pictures/0300009F.png) - -#### With C++ Statements (Programmatically) - -How would one move an object in a script? Since there is a tight -correspondence between what is seen on the screen and the object in -memory, changing the object changes it on the screen. For example, try -to do: - -``` {.cpp} -root[] a.SetX1(0.9) -``` - -This should change one of the coordinates of our line, but nothing -happens on the screen. Why is that? In short, the canvas is not updated -with each change for performance reasons. See "Updating the Pad". - -### Selecting Objects - - -#### The Middle Mouse Button - -Objects in a canvas, as well as in a pad, are stacked on top of each -other in the order they were drawn. Some objects may become "active" -objects, which mean they are reordered to be on top of the others. To -interactively make an object "active", you can use the middle mouse -button. In case of canvases or pads, the border becomes highlighted when -it is active. - -#### With C++ Statements (Programmatically) - -Frequently we want to draw in different canvases or pads. By default, -the objects are drawn in the active canvas. To activate a canvas you can -use the `TPad::cd()` method. - -``` {.cpp} -root[] c1->cd() -``` - -### Context Menus: the Right Mouse Button - - -The context menus are a way to interactively call certain methods of an -object. When designing a class, the programmer can add methods to the -context menu of the object by making minor changes to the header file. - -#### Using Context Menus - -On a ROOT canvas, you can right-click on any object and see the context -menu for it. The script `hsimple.C` draws a histogram. The image below -shows the context menus for some of the objects on the canvas. Next -picture shows that drawing a simple histogram involves as many as seven -objects. When selecting a method from the context menu and that method -has options, the user will be asked for numerical values or strings to -fill in the option. For example, `TAxis::SetTitle` will prompt you for a -string to use for the axis title. - -![Context menus of different objects in a canvas](pictures/030000A0.png) - -#### Structure of the Context Menus - -The curious reader will have noticed that each entry in the context menu -corresponds to a method of the class. Look for example to the menu named -`TAxis::xaxis`. `xaxis` is the name of the object and **`TAxis`** the -name of its class. If we look at the list of **`TAxis`** methods, for -example in , we see the -methods `SetTimeDisplay()` and` UnZoom()`, which appear also in the -context menu. - -There are several divisions in the context menu, separated by lines. The -top division is a list of the class methods; the second division is a -list of the parent class methods. The subsequent divisions are the -methods other parent classes in case of multiple inheritance. For -example, see the `TPaveText::title context -menu.` A **`TPaveText`** inherits from **`TAttLine`**, which has the -method `SetLineAttributes()`. - -#### Adding Context Menus for a Class - -For a method to appear in the context menu of the object it has to be -marked by `// *MENU*` in the header file. Below is the line from -`TAttLine.h` that adds the `SetLineAttribute` method to the context -menu. - -``` {.cpp} -virtual void SetLineAttributes(); // *MENU* -``` - -Nothing else is needed, since Cling knows the classes and their methods. -It takes advantage of that to create the context menu on the fly when -the object is clicking on. If you click on an axis, ROOT will ask the -interpreter what are the methods of the **`TAxis`** and which ones are -set for being displayed in a context menu. - -Now, how does the interpreter know this? Remember, when you build a -class that you want to use in the ROOT environment, you use `rootcling` -that builds the so-called stub functions and the dictionary. These -functions and the dictionary contain the knowledge of the used classes. -To do this, `rootcling` parses all the header files. ROOT has defined -some special syntax to inform Cling of certain things, this is done in -the comments so that the code still compiles with a C++ compiler. - -For example, you have a class with a `Draw()` method, which will display -itself. You would like a context menu to appear when on clicks on the -image of an object of this class. The recipe is the following: - -- The class has to contain the `ClassDef/ClassImp` macros - -- For each method you want to appear in the context menu, put a - comment after the declaration containing `*MENU*` or `*TOGGLE*` - depending on the behavior you expect. One usually uses Set methods - (setters). The `*TOGGLE*` comment is used to toggle a `boolean` data - field. In that case, it is safe to call the data field `fMyBool` - where `MyBool` is the name of the setter `SetMyBool`. Replace - `MyBool` with your own `boolean` variable. - -- You can specify arguments and the data members in which to store the - arguments. - -For example: - -``` {.cpp} -class MyClass : public TObject { -private: - int fV1; // first variable - double fV2; // second variable -public: - int GetV1() {return fV1;} - double GetV2() {return fV2;} - void SetV1(int x1) { fV1 = x1;} // *MENU* - void SetV2(double d2) { fV2 = d2;} // *MENU* - void SetBoth(int x1, double d2) {fV1 = x1; fV2 = d2;} - - ClassDef (MyClass,1) -} -``` - -To specify arguments: - -``` {.cpp} -void SetXXX(Int_t x1, Float_t y2); //*MENU* *ARGS={x1=>fV1} -``` - -This statement is in the comment field, after the \*MENU\*. If there is -more than one argument, these arguments are separated by commas, where -fX1 and fY2 are data fields in the same class. - -``` {.cpp} -void SetXXX(Int_t x1, Float_t y2); //*MENU* *ARGS={x1=>fX1,y2=>fY2} -``` - -If the arguments statement is present, the option dialog displayed when -selecting `SetXXX field` will show the values of variables. We indicate -to the system which argument corresponds to which data member of the -class. - -### Executing Events when a Cursor Passes on Top of an Object - - -This paragraph is for class designers. When a class is designed, it is -often desirable to include drawing methods for it. We will have a more -extensive discussion about this, but drawing an object in a canvas or a -pad consists in "attaching" the object to that pad. When one uses -`object.Draw()`, the object is NOT painted at this moment. It is only -attached to the active pad or canvas. - -Another method should be provided for the object to be painted, the -`Paint()` method. This is all explained in the next paragraph. As well -as `Draw()` and `Paint()`, other methods may be provided by the designer -of the class. When the mouse is moved or a button pressed/released, the -**`TCanvas`** function named `HandleInput()` scans the list of objects -in all it's pads and for each object calls some standard methods to make -the object react to the event (mouse movement, click or whatever). - -The second one is `DistancetoPrimitive(px,py)`. This function computes a -"distance" to an object from the mouse position at the pixel position -(`px`, `py`, see definition at the end of this paragraph) and returns -this distance in pixel units. The selected object will be the one with -the shortest computed distance. To see how this works, select the -"`Event Status`" item in the canvas "`Options`" menu. ROOT will display -one status line showing the picked object. If the picked object is, for -example, a histogram, the status line indicates the name of the -histogram, the position `x,y` in histogram coordinates, the channel -number and the channel content. - -It is nice for the canvas to know what the closest object from the mouse -is, but it's even nicer to be able to make this object react. The third -standard method to be provided is `ExecuteEvent()`. This method actually -does the event reaction. Its prototype is where `px` and `py` are the -coordinates at which the event occurred, except if the event is a key -press, in which case `px` contains the key code. - -``` {.cpp} -void ExecuteEvent(Int_t event, Int_t px, Int_t py); -``` - -Where `event` is the event that occurs and is one of the following -(defined in `Buttons.h`): - -``` {.cpp} -kNoEvent, kButton1Down, kButton2Down, -kButton3Down, kKeyDown, kButton1Up, -kButton2Up, kButton3Up, kButton1Motion, -kButton2Motion, kButton3Motion, kKeyPress, -kButton1Locate, kButton2Locate, kButton3Locate, -kKeyUp, kButton1Double, kButton2Double, -kButton3Double, kMouseMotion, kMouseEnter, -kMouseLeave -``` - -We hope the names are self-explanatory. - -Designing an `ExecuteEvent` method is not very easy, except if one wants -very basic treatment. We will not go into that and let the reader refer -to the sources of classes like **`TLine`** or **`TBox`**. Go and look at -their `ExecuteEvent` method! We can nevertheless give some reference to -the various actions that may be performed. For example, one often wants -to change the shape of the cursor when passing on top of an object. This -is done with the `SetCursor` method: - -``` {.cpp} -gPad->SetCursor(cursor) -``` - -The argument `cursor` is the type of cursor. It may be: - -``` {.cpp} -kBottomLeft, kBottomRight, kTopLeft, -kTopRight, kBottomSide, kLeftSide, -kTopSide, kRightSide, kMove, -kCross, kArrowHor, kArrowVer, -kHand, kRotate, kPointer, -kArrowRight, kCaret, kWatch -``` - -They are defined in `TVirtualX.h` and again we hope the names are -self-explanatory. If not, try them by designing a small class. It may -derive from something already known like **`TLine`**. - -Note that the `ExecuteEvent()` functions may in turn; invoke such -functions for other objects, in case an object is drawn using other -objects. You can also exploit at best the virtues of inheritance. See -for example how the class **`TArrow`** (derived from **`TLine`**) use or -redefine the picking functions in its base class. - -The last comment is that mouse position is always given in pixel units -in all these standard functions. `px=0` and `py=0` corresponds to the -top-left corner of the canvas. Here, we have followed the standard -convention in windowing systems. Note that user coordinates in a canvas -(pad) have the origin at the bottom-left corner of the canvas (pad). -This is all explained in the paragraph "The Coordinate Systems of a -Pad". - -## Graphical Containers: Canvas and Pad -\index{TPad} - - -We have talked a lot about canvases, which may be seen as windows. More -generally, a graphical entity that contains graphical objects is called -a Pad. A Canvas is a special kind of Pad. From now on, when we say -something about pads, this also applies to canvases. A pad (class -**`TPad`**) is a graphical container in the sense it contains other -graphical objects like histograms and arrows. It may contain other pads -(sub-pads) as well. A Pad is a linked list of primitives of any type -(graphs, histograms, shapes, tracks, etc.). It is a kind of display list. - -![The pad display list](pictures/pad_01.png) - -Drawing an object is nothing more than adding its pointer to this list. -Look for example at the code of `TH1::Draw()`. It is merely ten lines of -code. The last statement is `AppendPad()`. This statement calls method -of **`TObject`** that just adds the pointer of the object, here a -histogram, to the list of objects attached to the current pad. Since -this is a **`TObject`**'s method, every object may be "drawn", which -means attached to a pad. - -When is the painting done then ? The answer is: when needed. Every object -that derives from **`TObject`** has a `Paint()` method. It may be empty, -but for graphical objects, this routine contains all the instructions to -paint effectively it in the active pad. Since a Pad has the list of -objects it owns, it will call successively the `Paint()` method of each -object, thus re-painting the whole pad on the screen. If the object is a -sub-pad, its `Paint()` method will call the `Paint()` method of the -objects attached, recursively calling `Paint()` for all the objects. - -![Pad painting](pictures/pad_02.png) - -In some cases a pad need to be painted during a macro execution. To -force the pad painting `gPad->Update()` (see next section) should be performed. - -The list of primitives stored in the pad is also used to pick objects -and to interact with them. - -### The Global Pad: gPad - - -When an object is drawn, it is always in the so-called active pad. For -every day use, it is comfortable to be able to access the active pad, -whatever it is. For that purpose, there is a global pointer, called -***`gPad`***. It is always pointing to the active pad. If you want to -change the fill color of the active pad to blue but you do not know its -name, do this. - -``` {.cpp} -root[] gPad->SetFillColor(38) -``` - -To get the list of colors, go to the paragraph "Color and color -palettes" or if you have an opened canvas, click on the `View` menu, -selecting the `Colors` item. - -#### Finding an Object in a Pad - -Now that we have a pointer to the active pad, ***`gPad`*** and that we -know this pad contains some objects, it is sometimes interesting to -access one of those objects. The method `GetPrimitive()` of **`TPad`**, -i.e. `TPad::GetPrimitive(const char* name)` does exactly this. Since -most of the objects that a pad contains derive from **`TObject`**, they -have a name. The following statement will return a pointer to the object -`myobjectname` and put that pointer into the variable `obj`. As you can -see, the type of returned pointer is `TObject*`. - -``` {.cpp} -root[] obj = gPad->GetPrimitive("myobjectname") -(class TObject*)0x1063cba8 -``` - -Even if your object is something more complicated, like a histogram -**`TH1F`**, this is normal. A function cannot return more than one type. -So the one chosen was the lowest common denominator to all possible -classes, the class from which everything derives, **`TObject`**. How do -we get the right pointer then? Simply do a cast of the function output -that will transform the output (pointer) into the right type. For -example if the object is a **`TPaveLabel`**: - -``` {.cpp} -root[] obj = (TPaveLabel*)(gPad->GetPrimitive("myobjectname")) -(class TPaveLabel*)0x1063cba8 -``` - -This works for all objects deriving from **`TObject`**. However, a -question remains. An object has a name if it derives from **`TNamed`**, -not from **`TObject`**. For example, an arrow (**`TArrow`**) doesn't -have a name. In that case, the "name" is the name of the class. To know -the name of an object, just click with the right button on it. The name -appears at the top of the context menu. In case of multiple unnamed -objects, a call to `GetPrimitive("className")` returns the instance of -the class that was first created. To retrieve a later instance you can -use `GetListOfPrimitives()`, which returns a list of all the objects on -the pad. From the list you can select the object you need. - -#### Hiding an Object - -Hiding an object in a pad can be made by removing it from the list of -objects owned by that pad. This list is accessible by the -`GetListOfPrimitives()` method of **`TPad`**. This method returns a -pointer to a **`TList`**. Suppose we get the pointer to the object, we -want to hide, call it `obj` (see paragraph above). We get the pointer to -the list: - -``` {.cpp} -root[] li = gPad->GetListOfPrimitives() -``` - -Then remove the object from this list: - -``` {.cpp} -root[] li->Remove(obj) -``` - -The object will disappear from the pad as soon as the pad is updated -(try to resize it for example). If one wants to make the object -reappear: - -``` {.cpp} -root[] obj->Draw() -``` - -Caution, this will not work with composed objects, for example many -histograms drawn on the same plot (with the option "`same`"). There are -other ways! Try to use the method described here for simple objects. - -### The Coordinate Systems of a Pad - - -There are coordinate systems in a **`TPad`**: user coordinates, -normalized coordinates (NDC), and pixel coordinates. - -![Pad coordinate systems](pictures/080000A3.png) - -#### The User Coordinate System - -The most common is the user coordinate system. Most methods of -**`TPad`** use the user coordinates, and all graphic primitives have -their parameters defined in terms of user coordinates. By default, when -an empty pad is drawn, the user coordinates are set to a range from 0 to -1 starting at the lower left corner. At this point they are equivalent -of the NDC coordinates (see below). If you draw a high level graphical -object, such as a histogram or a function, the user coordinates are set -to the coordinates of the histogram. Therefore, when you set a point it -will be in the histogram coordinates. - -For a newly created blank pad, one may use `TPad::Range` to set the user -coordinate system. This function is defined as: - -``` {.cpp} -void Range(float x1,float y1,float x2,float y2) -``` - -The arguments `x1`, `x2` defines the new range in the x direction, and -the `y1`, `y2` define the new range in the y-direction. - -``` {.cpp} -root[] TCanvas MyCanvas ("MyCanvas") -root[] gPad->Range(-100,-100,100,100) -``` - -This will set the active pad to have both coordinates to go from -100 to -100, with the center of the pad at (0,0). You can visually check the -coordinates by viewing the status bar in the canvas. To display the -status bar select Event Status entry in the View canvas menu. - -![The status bar](pictures/020000A4.jpg) - -#### The Normalized Coordinate System (NDC) - -Normalized coordinates are independent of the window size and of the -user system. The coordinates range from 0 to 1 and (0, 0) corresponds to -the bottom-left corner of the pad. Several internal ROOT functions use -the NDC system (3D primitives, PostScript, log scale mapping to linear -scale). You may want to use this system if the user coordinates are not -known ahead of time. - -#### The Pixel Coordinate System - -The least common is the pixel coordinate system, used by functions such -as `DistancetoPrimitive()` and `ExecuteEvent()`. Its primary use is for -cursor position, which is always given in pixel coordinates. If -(`px,py`) is the cursor position, `px=0` and `py=0` corresponds to the -top-left corner of the pad, which is the standard convention in -windowing systems. - -#### Using NDC for a particular Object - -Most of the time, you will be using the user coordinate system. But -sometimes, you will want to use NDC. For example, if you want to draw -text always at the same place over a histogram, no matter what the -histogram coordinates are. There are two ways to do this. You can set -the NDC for one object or may convert NDC to user coordinates. Most -graphical objects offer an option to be drawn in NDC. For instance, a -line (**`TLine`**) may be drawn in NDC by using `DrawLineNDC()`. A latex -formula or a text may use `TText::SetNDC()` to be drawn in NDC -coordinates. - -### Converting between Coordinate Systems - - -There are a few utility functions in **`TPad`** to convert from one -system of coordinates to another. In the following table, a point is -defined by `(px,py)` in pixel coordinates, `(ux,uy)` in user -coordinates, `(ndcx,ndcy)` in normalized coordinates, (`apx`, `apy`) are -in absolute pixel coordinates. - -+-----------------------+----------------------------------+--------------------+ -| Conversion | TPad's Methods | Returns | -+-----------------------+----------------------------------+--------------------+ -| NDC to Pixel | `UtoPixel(ndcx)` | Int\_t | -| | | | -| | `VtoPixel(ndcy)` | Int\_t | -+-----------------------+----------------------------------+--------------------+ -| Pixel to User | `PixeltoX(px)` | Double\_t | -| | | | -| | `PixeltoY(py)` | Double\_t | -| | | | -| | `PixeltoXY(px,py,&ux,&uy)` | Double\_t ux,uy | -+-----------------------+----------------------------------+--------------------+ -| User to Pixel | `XtoPixel(ux)` | Int\_t | -| | | | -| | `YtoPixel(uy)` | Int\_t | -| | | | -| | `XYtoPixel(ux,uy,&px,&py)` | Int\_t px,py | -+-----------------------+----------------------------------+--------------------+ -| User to absolute | `XtoAbsPixel(ux)` | Int\_t | -| pixel | | | -| | `YtoAbsPixel(uy)` | Int\_t | -| | | | -| | `XYtoAbsPixel(ux,uy,&apx,&apy)` | Int\_t apx,apy | -+-----------------------+----------------------------------+--------------------+ -| Absolute pixel to | `AbsPixeltoX(apx)` | Double\_t | -| user | | | -| | `AbsPixeltoY(apy)` | Double\_t | -| | | | -| | `AbsPixeltoXY(apx,apy,&ux,&uy)` | Double\_t ux,uy | -+-----------------------+----------------------------------+--------------------+ - -Note: all the pixel conversion functions along the Y axis consider that -`py=0` is at the top of the pad except `PixeltoY()` which assume that -the position `py=0` is at the bottom of the pad. To make `PixeltoY()` -converting the same way as the other conversion functions, it should be -used the following way (`p` is a pointer to a **`TPad`**): - -``` {.cpp} -p->PixeltoY(py - p->GetWh()); -``` - -### Dividing a Pad into Sub-pads - - -Dividing a pad into sub pads in order for instance to draw a few -histograms, may be done in two ways. The first is to build pad objects -and to draw them into a parent pad, which may be a canvas. The second is -to automatically divide a pad into horizontal and vertical sub pads. - -#### Creating a Single Sub-pad - -The simplest way to divide a pad is to build sub-pads in it. However, -this forces the user to explicitly indicate the size and position of -those sub-pads. Suppose we want to build a sub-pad in the active pad -(pointed by ***`gPad`***). First, we build it, using a **`TPad`** -constructor: - -``` {.cpp} -root[] spad1 = new TPad("spad1","The first subpad",.1,.1,.5,.5) -``` - -One gives the coordinates of the lower left point (0.1, 0.1) and of the -upper right one (0.5, 0.5). These coordinates are in NDC. This means -that they are independent of the user coordinates system, in particular -if you have already drawn for example a histogram in the mother pad. The -only thing left is to draw the pad: - -``` {.cpp} -root[] spad1->Draw() -``` - -If you want more sub-pads, you have to repeat this procedure as many -times as necessary. - -#### Dividing a Canvas into Sub-Pads - -The manual way of dividing a pad into sub-pads is sometimes very -tedious. There is a way to automatically generate horizontal and -vertical sub-pads inside a given pad. - -``` {.cpp} -root[] pad1->Divide(3,2) -``` - -![Dividing a pad into 6 sub-pads](pictures/030000A5.png) - -![Dividing a pad into 6 sub-pads](pictures/020000A6.jpg) - -If `pad1` is a pad then, it will divide the pad into 3 columns of 2 -sub-pads. The generated sub-pads get names `pad1_i` where the index -`i=1` to `nxm` (in our case `pad1_1`, `pad1_2`...`pad1_6)`. The names -`pad1_1 `etc... correspond to new variables in Cling, so you may use them -as soon as the executed method was `pad->Divide()`. However, in a -compiled program, one has to access these objects. Remember that a pad -contains other objects and that these objects may themselves be pads. So -we can use the `GetPrimitive()` method: - -``` {.cpp} -TPad* pad1_1 = (TPad*)(pad1->GetPrimitive("pad1_1")) -``` - -One question remains. In case one does an automatic divide, how one can -set the default margins between pads? This is done by adding two -parameters to `Divide()`, which are the margins in `x` and `y`: - -``` {.cpp} -root[] pad1->Divide(3,2,0.1,0.1) -``` - -The margins are here set to 10% of the parent pad width. - -### Updating the Pad - - -For performance reasons, a pad is not updated with every change. For -example, changing the coordinates of the pad does not automatically -redraw it. Instead, the pad has a "bit-modified" that triggers a redraw. -This bit is automatically set by: - -- Touching the pad with the mouse - for example resizing it with the - mouse. - -- Finishing the execution of a script. - -- Adding a new primitive or modifying some primitives for example the - name and title of an object. - -- You can also set the "bit-modified" explicitly with the `Modified` - method: - - ``` {.cpp} - // the pad has changed - root[] pad1->Modified() - // recursively update all modified pads: - root[] c1->Update() - ``` - - A subsequent call to `TCanvas::Update()` scans the list of sub-pads - and repaints the pads declared modified. - -In compiled code or in a long macro, you may want to access an object -created during the paint process. To do so, you can force the painting -with a `TCanvas::Update()`. For example, a **`TGraph`** creates a -histogram (**`TH1`**) to paint itself. In this case the internal -histogram obtained with `TGraph::GetHistogram()` is created only after -the pad is painted. The pad is painted automatically after the script is -finished executing or if you force the painting with `TPad::Modified()` -followed by a `TCanvas::Update()`. Note that it is not necessary to call -`TPad::Modified()` after a call to `Draw()`. The "bit-modified" is set -automatically by `Draw()`. A note about the "bit-modified" in sub pads: -when you want to update a sub pad in your canvas, you need to call -`pad->Modified()` rather than `canvas->Modified()`, and follow it with a -`canvas->Update()`. If you use `canvas->Modified()`, followed by a call -to `canvas->Update()`, the sub pad has not been declared modified and it -will not be updated. Also note that a call to `pad->Update()` where pad -is a sub pad of canvas, calls `canvas->Update()` and recursively updates -all the pads on the canvas. - -### Making a Pad Transparent - - -As we will see in the paragraph "Fill Attributes", a fill style (type of -hatching) may be set for a pad. - -``` {.cpp} -root[] pad1->SetFillStyle(istyle) -``` - -This is done with the `SetFillStyle` method where `istyle` is a style -number, defined in "Fill Attributes". A special set of styles allows -handling of various levels of transparency. These are styles number 4000 -to 4100, 4000 being fully transparent and 4100 fully opaque. So, suppose -you have an existing canvas with several pads. You create a new pad -(transparent) covering for example the entire canvas. Then you draw your -primitives in this pad. The same can be achieved with the graphics -editor. For example: - -``` {.cpp} -root[] .x tutorials/hist/hist015_TH1_read_and_draw.C -root[] TPad *newpad=new TPad("newpad","Transparent pad",0,0,1,1); -root[] newpad->SetFillStyle(4000); -root[] newpad->Draw(); -root[] newpad->cd(); -root[] // create some primitives, etc -``` - -### Setting the Log Scale - - -Setting the scale to logarithmic or linear is an attribute of the pad, -not the axis or the histogram. The scale is an attribute of the pad -because you may want to draw the same histogram in linear scale in one -pad and in log scale in another pad. Frequently, we see several -histograms on top of each other in the same pad. It would be very -inconvenient to set the scale attribute for each histogram in a pad. - -Furthermore, if the logic was set in the histogram class (or each -object) the scale setting in each `Paint` method of all objects should -be tested. - -If you have a pad with a histogram, a right-click on the pad, outside of -the histograms frame will convince you. The `SetLogx()`, `SetLogy()` and -`SetLogz()` methods are there. As you see, **`TPad`** defines log scale -for the two directions `x` and `y` plus `z` if you want to draw a 3D -representation of some function or histogram. - -The way to set log scale in the x direction for the active pad is: - -``` {.cpp} -root[] gPad->SetLogx(1) -``` - -To reset log in the z direction: - -``` {.cpp} -root[] gPad->SetLogz(0) -``` - -If you have a divided pad, you need to set the scale on each of the -sub-pads. Setting it on the containing pad does not automatically -propagate to the sub-pads. Here is an example of how to set the log -scale for the x-axis on a canvas with four sub-pads: - -``` {.cpp} -root[] TCanvas MyCanvas("MyCanvas","My Canvas") -root[] MyCanvas->Divide(2,2) -root[] MyCanvas->cd(1) -root[] gPad->SetLogx() -root[] MyCanvas->cd(2) -root[] gPad->SetLogx() -root[] MyCanvas->cd(3) -root[] gPad->SetLogx() -``` - -### WaitPrimitive method - - -When the `TPad::WaitPrimitive()` method is called with no arguments, it -will wait until a double click or any key pressed is executed in the -canvas. A call to `gSystem->Sleep(10)` has been added in the loop to -avoid consuming at all the CPU. This new option is convenient when -executing a macro. By adding statements like: - -``` {.cpp} -canvas->WaitPrimitive(); -``` - -You can monitor the progress of a running macro, stop it at convenient -places with the possibility to interact with the canvas and resume the -execution with a double click or a key press. - -### Locking the Pad - - -You can make the **`TPad`** non-editable. Then no new objects can be -added, and the existing objects and the pad can not be changed with the -mouse or programmatically. By default the **`TPad`** is editable. - -``` {.cpp} -TPad::SetEditable(kFALSE) -``` - -## Graphical Objects - - -In this paragraph, we describe the various simple 2D graphical objects -defined in ROOT. Usually, one defines these objects with their -constructor and draws them with their `Draw()` method. Therefore, the -examples will be very brief. Most graphical objects have line and fill -attributes (color, width) that will be described in "Graphical objects -attributes". If the user wants more information, the class names are -given and they may refer to the online developer documentation. This is -especially true for functions and methods that set and get internal -values of the objects described here. By default 2D graphical objects -are created in User Coordinates with (0, 0) in the lower left corner. - -### Lines, Arrows and Polylines - - -The simplest graphical object is a line. It is implemented in the -**`TLine`** class. The line constructor is: - -``` {.cpp} -TLine(Double_t x1,Double_t y1,Double_t x2,Double_t y2) -``` - -The arguments `x1`, `y1`, `x2`, `y2` are the coordinates of the first -and second point. It can be used: - -``` {.cpp} -root[] l = new TLine(0.2,0.2,0.8,0.3) -root[] l->Draw() -``` - -The arrow constructor is: - -``` {.cpp} -TArrow(Double_t x1, Double_t y1, - Double_t x2, Double_t y2, - Float_t arrowsize, Option_t *option) -``` - -It defines an arrow between points `x1,y1` and `x2,y2`. The arrow size -is in percentage of the pad height. The `option` parameter has the -following meanings: - -![](pictures/020000A7.jpg) "\>" - -![](pictures/020000A8.jpg) "\<|" - -![](pictures/020000A9.jpg) "\<" - -![](pictures/020000AA.jpg) "|\>" - -![](pictures/020000AB.jpg) "\<\>" - -![](pictures/020000AC.jpg) "\<|\>" - -Once an arrow is drawn on the screen, one can: - -- click on one of the edges and move this edge. - -- click on any other arrow part to move the entire arrow. - -![Different arrow formats](pictures/030000AD.png) - -If `FillColor` is 0, an open triangle is drawn; else a full triangle is -filled with the set fill color. If `ar` is an arrow object, fill color -is set with: - -``` {.cpp} -ar.SetFillColor(icolor); -``` - -Where `icolor` is the color defined in "Color and Color Palettes". - -The default-opening angle between the two sides of the arrow is 60 -degrees. It can be changed with the method `ar->SetAngle(angle)`, where -angle is expressed in degrees. - -A poly-line is a set of joint segments. It is defined by a set of N -points in a 2D space. Its constructor is: - -``` {.cpp} -TPolyLine(Int_t n,Double_t* x,Double_t* y,Option_t* option) -``` - -Where `n` is the number of points, and `x` and `y` are arrays of `n` -elements with the coordinates of the points. **`TPolyLine`** can be used -by it self, but is also a base class for other objects, such as curly -arcs. - -### Circles and Ellipses - - -An ellipse can be truncated and rotated. It is defined by its center -`(x1,y1)` and two radii `r1` and `r2`. A minimum and maximum angle may -be specified `(phimin,phimax)`. The ellipse may be rotated with an angle -`theta`. All these angles are in degrees. The attributes of the outline -line are set via **`TAttLine`**, of the fill area - via **`TAttFill`** -class. They are described in "Graphical Objects Attributes". - -![Different types of ellipses](pictures/030000AE.png) - -When an ellipse sector is drawn only, the lines between the center and -the end points of the sector are drawn by default. By specifying the -drawn option "`only`", these lines can be avoided. Alternatively, the -method `SetNoEdges()` can be called. To remove completely the ellipse -outline, specify zero (0) as a line style. - -The **`TEllipse`** constructor is: - -``` {.cpp} -TEllipse(Double_t x1, Double_t y1, Double_t r1, Double_t r2, - Double_t phimin, Double_t phimax, Double_t theta) -``` - -An ellipse may be created with: - -``` {.cpp} -root[] e = new TEllipse(0.2,0.2,0.8,0.3) -root[] e->Draw() -``` - -### Rectangles - - -The class **`TBox`** defines a rectangle. It is a base class for many -different higher-level graphical primitives. Its bottom left coordinates -`x1`, `y1` and its top right coordinates `x2`, `y2`, defines a box. The -constructor is: - -``` {.cpp} -TBox(Double_t x1,Double_t y1,Double_t x2,Double_t y2) -``` - -It may be used as in: - -``` {.cpp} -root[] b = new TBox(0.2,0.2,0.8,0.3) -root[] b->SetFillColor(5) -root[] b->Draw() -``` - -![A rectangle with a border](pictures/020000AF.jpg) - -A **`TWbox`** is a rectangle (**`TBox`**) with a border size and a -border mode. The attributes of the outline line and of the fill area are -described in "Graphical Objects Attributes" - -### Markers - - -A marker is a point with a fancy shape! The possible markers are shown -in the next figure. - -![Markers](pictures/030000B0.png) - -The marker constructor is: - -``` {.cpp} -TMarker(Double_t x,Double_t y,Int_t marker) -``` - -The parameters `x` and `y` are the marker coordinates and `marker` is -the marker type, shown in the previous figure. Suppose the pointer `ma` -is a valid marker. The marker size is set via `ma->SetMarkerSize(size)`, -where `size` is the desired size. Note, that the marker types 1, 6 and 7 -(the dots) cannot be scaled. They are always drawn with the same number -of pixels. `SetMarkerSize` does not apply on them. To have a "scalable -dot" a circle shape should be used instead, for example, the marker type -20. The default marker type is 1, if `SetMarkerStyle` is not specified. -It is the most common one to draw scatter plots. - -![Different marker sizes](pictures/030000B1.png) - -![Different marker sizes](pictures/030000B2.png) - -The user interface for changing the marker color, style and size looks -like shown in this picture. It takes place in the editor frame anytime -the selected object inherits the class **`TAttMarker`**. - -Non-symmetric symbols should be used carefully in plotting. The next two -graphs show how the misleading a careless use of symbols can be. The two -plots represent the same data sets but because of a bad symbol choice, -the two on the top appear further apart from the next example. - -![The use of non-symmetric markers](pictures/030000B3.png) - -A **`TPolyMaker`** is defined by an array on N points in a 2D space. At -each point `x[i]`, `y[i]` a marker is drawn. The list of marker types is -shown in the previous paragraph. The marker attributes are managed by -the class **`TAttMarker`** and are described in "Graphical Objects -Attributes". The **`TPolyMarker`** constructor is: - -``` {.cpp} -TPolyMarker(Int_t n,Double_t *x,Double_t *y,Option_t *option) -``` - -Where `x` and `y` are arrays of coordinates for the `n` points that form -the poly-marker. - -### Curly and Wavy Lines for Feynman Diagrams - - -This is a peculiarity of particle physics, but we do need sometimes to -draw Feynman diagrams. Our friends working in banking can skip this -part. A set of classes implements curly or wavy poly-lines typically -used to draw Feynman diagrams. Amplitudes and wavelengths may be -specified in the constructors, via commands or interactively from -context menus. These classes are **`TCurlyLine`** and **`TCurlyArc`**. -These classes make use of **`TPolyLine`** by inheritance; `ExecuteEvent` -methods are highly inspired from the methods used in **`TPolyLine`** and -**`TArc`**. - -![The picture generated by the tutorial macro -feynman.C](pictures/030000B4.png) - -The **`TCurlyLine`** constructor is: - -``` {.cpp} -TCurlyLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2, - Double_t wavelength, Double_t amplitude) -``` - -The coordinates `(x1`, `y1)` define the starting point, `(x2`, `y2)` - -the end-point. The `wavelength` and the `amplitude` are given in percent -of the pad height. - -The **`TCurlyArc`** constructor is: - -``` {.cpp} -TCurlyArc(Double_t x1, Double_t y1, Double_t rad, - Double_t phimin, Double_t phimax, - Double_t wavelength, Double_t amplitude) -``` - -The curly arc center is `(x1`, `y1)` and the radius is `rad`. The -wavelength and the amplitude are given in percent of the line length. -The parameters `phimin` and `phimax` are the starting and ending angle -of the arc (given in degrees). Refer to -`$ROOTSYS/tutorials/visualisation/graphics/feynman.C` for the script that built the -figure above. - -### Text and Latex Mathematical Expressions - - -Text displayed in a pad may be embedded into boxes, called paves -(**`TPaveLabel`**), or titles of graphs or many other objects but it can -live a life of its own. All text displayed in ROOT graphics is an object -of class **`TText`**. For a physicist, it will be most of the time a -**`TLatex`** expression (which derives from **`TText`**). **`TLatex`** -has been conceived to draw mathematical formulas or equations. Its -syntax is very similar to the Latex in mathematical mode. - -#### Subscripts and Superscripts - -Subscripts and superscripts are made with the `_` and `^` commands. -These commands can be combined to make complex subscript and superscript -expressions. You may choose how to display subscripts and superscripts -using the 2 functions `SetIndiceSize(Double_t)` and -`SetLimitIndiceSize(Int_t)`. Examples of what can be obtained using -subscripts and superscripts: - -+-----------------+---------+------------------+-----------+---------------------+----------------+ -| The expression | Gives | The expression | Gives | The expression | Gives | -+-----------------+---------+------------------+-----------+---------------------+----------------+ -| **`x^{2y}`** |$x^{2y}$ | **`x^{y^{2}}`** |$x^{y^{2}}$| **`x_{1}^{y_{1}}`** | $x_{1}^{y_{1}}$| -+-----------------+---------+------------------+-----------+---------------------+----------------+ -| **`x_{2y}`** |$x_{2y}$ | **`x^{y_{1}}`** |$x^{y_{1}}$| **`x_{1}^{y}`** | $x_{1}^{y}$ | -+-----------------+---------+------------------+-----------+---------------------+----------------+ - -#### Fractions - -Fractions denoted by the / symbol are made in the obvious way. The -`#frac` command is used for large fractions in displayed formula; it has -two arguments: the numerator and the denominator. For example, the -equation x = y + z 2 y 2 + 1 is obtained by following expression -`x=#frac{y+z/2}{y^{2}+1}`. - -#### Roots - -The `#sqrt` command produces the square ROOT of its argument; it has an -optional first argument for other roots. - -Example: `#sqrt{10} #sqrt[3]{10}` ![](pictures/030000BC.png) - -#### Delimiters - -You can produce three kinds of proportional delimiters. - -`#[]{....}` or "à la" Latex - -`#left[.....#right] `big square brackets - -`#{}{....} or #left{.....#right}`big curly brackets - -`#||{....} or #left|.....#right|`big absolute value symbol - -`#(){....} or #left(.....#right)`big parenthesis - -#### Changing Style in Math Mode - -You can change the font and the text color at any moment using: - -`#font[font-number]{...}` and `#color[color-number]{...}` - -#### Line Splitting - -A **`TLatex`** string may be split in two with the following command: -`#splitline{top}{bottom}`. **`TAxis`** and **`TGaxis`** objects can take -advantage of this feature. For example, the date and time could be shown -in the time axis over two lines with: -`#splitline{21 April 2003}{14:23:56}` - -### Greek Letters - - -The command to produce a lowercase Greek letter is obtained by adding -`#` to the name of the letter. For an uppercase Greek letter, just -capitalize the first letter of the command name. - -``` {.cpp} -#alpha #beta #chi #delta #varepsilon #phi -#gamma #eta #iota #varphi #kappa #lambda -#mu #nu #omicron #pi #theta #rho -#sigma #tau #upsilon #varomega #omega #xi -#psi #zeta #Alpha #Beta #Chi #Delta -#Epsilon #Phi #Gamma #Eta #Iota #Kappa -#vartheta #Lambda #Mu #Nu #Omicron #Pi -#Theta #Rho #Sigma #Tau #Upsilon #Omega -#varsigma #Xi #Psi #epsilon #varUpsilon #Zeta -``` - -![](pictures/030000BD.png) - -### Mathematical Symbols - - -![](pictures/030000BE.png) - -**`TLatex`** can make mathematical and other symbols. A few of them, -such as `+` and `>`, are produced by typing the corresponding keyboard -character. Others are obtained with the commands as shown in the table -above. - -#### Accents, Arrows and Bars - -Symbols in a formula are sometimes placed one above another. -**`TLatex`** provides special commands for that. - -`#hat{a} = `hat - -`#check = `inverted hat - -`#acute = `acute - -`#grave = `accent grave - -`#dot = `derivative - -`#ddot = `double derivative - -`#tilde = `tilde - -`#slash = `special sign. Draw a slash on top of the text between -brackets for example - -`#slash{E}_{T} `generates "Missing ET" - -a \_ is obtained with `#bar{a}` - -a -\> is obtained with `#vec{a}` - -#### Example 1 - -The script `$ROOTSYS/tutorials/visualisation/graphics/latex.C:` - -``` {.cpp} -{ - TCanvas c1("c1","Latex",600,700); - TLatex l; - l.SetTextAlign(12); - l.SetTextSize(0.04); - - l.DrawLatex(0.1,0.8,"1) C(x) = d #sqrt{#frac{2}{#lambdaD}} - #int^{x}_{0}cos(#frac{#pi}{2}t^{2})dt"); - l.DrawLatex(0.1,0.6,"2) C(x) = d #sqrt{#frac{2}{#lambdaD}} - #int^{x}cos(#frac{#pi}{2}t^{2})dt"); - l.DrawLatex(0.1,0.4,"3) R = |A|^{2} = - #frac{1}{2}(#[]{#frac{1}{2}+C(V)}^{2}+ - #[]{#frac{1}{2}+S(V)}^{2})"); - l.DrawLatex(0.1,0.2,"4) F(t) = #sum_{i= - -#infty}^{#infty}A(i)cos#[]{#frac{i}{t+i}}"); -} -``` - -![The picture generated by the tutorial macro -latex.C](pictures/020000C1.jpg) - -#### Example 2 - -The script `$ROOTSYS/tutorials/visualisation/graphics/latex2.C:` - -``` {.cpp} -{ - TCanvas c1("c1","Latex",600,700); - TLatex l; - l.SetTextAlign(23); - l.SetTextSize(0.1); - l.DrawLatex(0.5,0.95,"e^{+}e^{-}#rightarrowZ^{0} - #rightarrowI#bar{I}, q#bar{q}"); - l.DrawLatex(0.5,0.75,"|#vec{a}#bullet#vec{b}|= - #Sigmaa^{i}_{jk}+b^{bj}_{i}"); - l.DrawLatex(0.5,0.5,"i(#partial_{#mu}#bar{#psi}#gamma^{#mu} - +m#bar{#psi}=0 - #Leftrightarrow(#Box+m^{2})#psi=0"); - l.DrawLatex(0.5,0.3,"L_{em}=eJ^{#mu}_{em}A_{#mu} , - J^{#mu}_{em}=#bar{I}#gamma_{#mu}I - M^{j}_{i}=#SigmaA_{#alpha}#tau^{#alphaj}_{i}"); -} -``` - -![The picture generated by the tutorial macro -latex2.C](pictures/020000C2.jpg) - -#### Example 3 - -The script `$ROOTSYS/tutorials/visualisation/graphics/latex3.C`: - -``` {.cpp} -{ - TCanvas c1("c1"); - TPaveText pt(.1,.5,.9,.9); - pt.AddText("#frac{2s}{#pi#alpha^{2}} - #frac{d#sigma}{dcos#theta} (e^{+}e^{-} - #rightarrow f#bar{f} ) = "); - pt.AddText("#left| #frac{1}{1 - #Delta#alpha} #right|^{2} - (1+cos^{2}#theta"); - pt.AddText("+ 4 Re #left{ #frac{2}{1 - #Delta#alpha} #chi(s) - #[]{#hat{g}_{#nu}^{e}#hat{g}_{#nu}^{f} - (1 + cos^{2}#theta) + 2 #hat{g}_{a}^{e} - #hat{g}_{a}^{f} cos#theta) } #right}"); - pt.SetLabel("Born equation"); - pt.Draw(); -} -``` - -![The picture generated by the tutorial macro -latex3.C](pictures/020000C3.jpg) - -### Text in a Pad - - -Text displayed in a pad may be embedded into boxes, called paves, or may -be drawn alone. In any case, it is recommended to use a Latex -expression, which is covered in the previous paragraph. Using -**`TLatex`** is valid whether the text is embedded or not. In fact, you -will use Latex expressions without knowing it since it is the standard -for all the embedded text. A pave is just a box with a border size and a -shadow option. The options common to all types of paves and used when -building those objects are the following: - -`option = "T"` top frame - -`option = "B"` bottom frame - -`option = "R"` right frame - -`option = "L"` left frame - -`option = "NDC" x1,y1,x2,y2` are given in NDC - -`option = "ARC"` corners are rounded - -We will see the practical use of these options in the description of the -more functional objects like `TPaveLabels`. There are several categories -of paves containing text: **`TPaveLabel`**, **`TPaveText`** and -**`TPavesText`**. `TPaveLabels` are panels containing one line of text. -They are used for labeling. - -``` {.cpp} -TPaveLabel(Double_t x1, Double_t y1, Double_t x2, Double_t y2, - const char *label, Option_t *option) -``` - -Where (`x1`, `y1`) are the coordinates of the bottom left corner, -`(x2,y2)` - coordinates of the upper right corner. "`label`" is the text -to be displayed and "`option`" is the drawing option, described above. -By default, the border size is 5 and the option is "`br`". If one wants -to set the border size to some other value, one may use the method -`SetBorderSize()`. For example, suppose we have a histogram, which -limits are (-100,100) in the x direction and (0, 1000) in the y -direction. The following lines will draw a label in the center of the -histogram, with no border. If one wants the label position to be -independent of the histogram coordinates, or user coordinates, one can -use the option "`NDC`". See "The Coordinate Systems of a Pad". - -``` {.cpp} -root[] pl = new TPaveLabel(-50,0,50,200,"Some text") -root[] pl->SetBorderSize(0) -root[] pl->Draw() -``` - -![`PaveLabels` drawn with different options](pictures/060000C4.png) - -A **`TPaveLabel`** can contain only one line of text. A **`TPaveText`** -may contain several lines. This is the only difference. This picture -illustrates and explains some of the points of **`TPaveText`**. Once a -**`TPaveText`** is drawn, a line can be added or removed by brining up -the context menu with the mouse. - -![PaveText examples](pictures/030000C5.png) - -A **`TPavesText`** is a stack of text panels (see **`TPaveText`**). One -can set the number of stacked panels at building time. It has the -following constructor: By default, the number of stacked panels is 5, -`option=`"`br`". - -``` {.cpp} -TPavesText(Double_t x1, Double_t y1, Double_t x2, Double_t y2, -Int_t npaves, Option_t* option) -``` - -![A PaveText example](pictures/030000C6.png) - -### The TeX Processor TMathText - - -TMathText's purpose is to write mathematical equations, exactly as TeX -would do it. The syntax is the same as the TeX's one. - -The script `$ROOTSYS/tutorials/visualisation/graphics/tmathtex.C`: - -gives the following output: - -![A TMathText example](pictures/mathtext.png) - -`TMathText` uses plain TeX syntax and uses "\\" as control instead of -"\#". If a piece of text containing "\\" is given to `TLatex` then -`TMathText` is automatically invoked. Therefore, as histograms' titles, -axis titles, labels etc ... are drawn using `TLatex`, the `TMathText` -syntax can be used for them also. - -## Axis - - -The axis objects are automatically built by various high level objects -such as histograms or graphs. Once build, one may access them and change -their characteristics. It is also possible, for some particular purposes -to build axis on their own. This may be useful for example in the case -one wants to draw two axis for the same plot, one on the left and one on -the right. - -For historical reasons, there are two classes representing axis. -**`TAxis`** \* `axis` is the axis object, which will be returned when -calling the `TH1::GetAxis()` method. - -``` {.cpp} -TAxis *axis = histo->GetXaxis() -``` - -Of course, you may do the same for `Y` and `Z`-axis. The graphical -representation of an axis is done with the **`TGaxis`** class. The -histogram classes and **`TGraph`** generate instances of this class. -This is internal and the user should not have to see it. - -### Axis Title - - -The axis title is set, as with all named objects, by - -``` {.cpp} -axis->SetTitle("Whatever title you want"); -``` - -When the axis is embedded into a histogram or a graph, one has to first -extract the axis object: - -``` {.cpp} -h->GetXaxis()->SetTitle("Whatever title you want") -``` - -### Axis Options and Characteristics - - -The axis options are most simply set with the styles. The available -style options controlling specific axis options are the following: - -``` {.cpp} -TAxis *axis = histo->GetXaxis(); -axis->SetAxisColor(Color_t color = 1); -axis->SetLabelColor(Color_t color = 1); -axis->SetLabelFont(Style_t font = 62); -axis->SetLabelOffset(Float_t offset = 0.005); -axis->SetLabelSize(Float_t size = 0.04); -axis->SetNdivisions(Int_t n = 510, Bool_t optim = kTRUE); -axis->SetNoExponent(Bool_t noExponent = kTRUE); -axis->SetTickLength(Float_t length = 0.03); -axis->SetTitleOffset(Float_t offset = 1); -axis->SetTitleSize(Float_t size = 0.02); -``` - -The getters corresponding to the described setters are also available. -The general options, not specific to axis, as for instance -`SetTitleTextColor()` are valid and do have an effect on axis -characteristics. - -### Setting the Number of Divisions - - -Use `TAxis::SetNdivisions(ndiv,optim)` to set the number of divisions -for an axis. The `ndiv` and `optim` are as follows: - -- `ndiv = N1 + 100*N2 + 10000*N3` - -- `N1 =` number of first divisions. - -- `N2 =` number of secondary divisions. - -- `N3 =` number of tertiary divisions. - -- `optim = kTRUE ` (default), the divisions' number will be optimized - around the specified value. - -- `optim = kFALSE, ` or n \< 0, the axis will be forced to use exactly - n divisions. - -For example: - -`ndiv = 0`: no tick marks. - -`ndiv = 2`: 2 divisions, one tick mark in the middle of the axis. - -`ndiv = 510`: 10 primary divisions, 5 secondary divisions - -`ndiv = -10`: exactly 10 primary divisions - -### Zooming the Axis - - -You can use `TAxis::SetRange` or `TAxis::SetRangeUser` to zoom the axis. - -``` {.cpp} -TAxis::SetRange(Int_t binfirst,Int_t binlast) -``` - -The `SetRange` method parameters are bin numbers. They are not axis. For -example if a histogram plots the values from 0 to 500 and has 100 bins, -`SetRange(0,10)` will cover the values 0 to 50. The parameters for -`SetRangeUser` are user coordinates. If the start or end is in the -middle of a bin the resulting range is approximation. It finds the low -edge bin for the start and the high edge bin for the high. - -``` {.cpp} -TAxis::SetRangeUser(Axis_t ufirst,Axis_t ulast) -``` - -Both methods, `SetRange` and `SetRangeUser`, are in the context menu of -any axis and can be used interactively. In addition, you can zoom an -axis interactively: click on the axis on the start, drag the cursor to -the end, and release the mouse button. - -### Drawing Axis Independently of Graphs or Histograms - - -An axis may be drawn independently of a histogram or a graph. This may -be useful to draw for example a supplementary axis for a graph. In this -case, one has to use the **`TGaxis`** class, the graphical -representation of an axis. One may use the standard constructor for this -kind of objects: - -``` {.cpp} -TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, - Double_t wmin, Double_t wmax, Int_t ndiv = 510, - Option_t* chopt,Double_t gridlength = 0) -``` - -The arguments `xmin, ymin` are the coordinates of the axis' start in the -user coordinates system, `and xmax, ymax` are the end coordinates. The -arguments `wmin` and `wmax` are the minimum (at the start) and maximum -(at the end) values to be represented on the axis; `ndiv` is the number -of divisions. The options, given by the "`chopt`" string are the -following: - -- `chopt = 'G'`: logarithmic scale, default is linear. - -- `chopt = 'B'`: Blank axis (it is useful to superpose the axis). - -Instead of the `wmin,wmax` arguments of the normal constructor, i.e. the -limits of the axis, the name of a **`TF1`** function can be specified. -This function will be used to map the user coordinates to the axis -values and ticks. - -The constructor is the following: - -``` {.cpp} -TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, - const char* funcname, Int_t ndiv=510, - Option_t* chopt, Double_t gridlength=0) -``` - -In such a way, it is possible to obtain exponential evolution of the -tick marks position, or even decreasing. In fact, anything you like. - -### Orientation of Tick Marks on Axis - - -Tick marks are normally drawn on the positive side of the axis, however, -if `xmin = xmax`, then negative. - -- `chopt = '+': ` tick marks are drawn on Positive side. (Default) - -- `chopt = '-': ` tick marks are drawn on the negative side. - -- `chopt = '+-':` tick marks are drawn on both sides of the axis. - -- `chopt = ‘U': ` unlabeled axis, default is labeled. - -### Labels - - -#### Position - -Labels are normally drawn on side opposite to tick marks. However, -`chopt = '='`: on Equal side. The function `TAxis::CenterLabels()` sets -the bit `kCenterLabels` and it is visible from **`TAxis`** context menu. -It centers the bin labels and it makes sense only when the number of -bins is equal to the number of tick marks. The class responsible for -drawing the axis **`TGaxis`** inherits this property. - -#### Orientation - -Labels are normally drawn parallel to the axis. However, if -`xmin = xmax`, then they are drawn orthogonal, and if `ymin=ymax` they -are drawn parallel. - -#### Labels for Exponents - -By default, an exponent of the form 10\^N is used when the label values -are either all very small or very large. One can disable the exponent by -calling: - -``` {.cpp} -TAxis::SetNoExponent(kTRUE) -``` - -Note that this option is implicitly selected if the number of digits to -draw a label is less than the `fgMaxDigits` global member. If the -property `SetNoExponent` was set in **`TAxis`** (via -`TAxis::SetNoExponent)`, the **`TGaxis`** will inherit this property. -**`TGaxis`** is the class responsible for drawing the axis. The method -`SetNoExponent` is also available from the axis context menu. - -![Y-axis with and without exponent labels](pictures/030000C7.png) - -#### Number of Digits in Labels - -`TGaxis::fgMaxDigits` is the maximum number of digits permitted for the -axis labels above which the notation with 10\^N is used. It must be -greater than 0. By default `fgMaxDigits` is 5 and to change it use the -`TGaxis::SetMaxDigits` method. For example to set `fgMaxDigits` to -accept 6 digits and accept numbers like 900000 on an axis call: - -``` {.cpp} -TGaxis::SetMaxDigits(6) -``` - -#### Tick Mark Positions - -Labels are centered on tick marks. However, if `xmin = xmax`, then they -are right adjusted. - -- `chopt = 'R'`: labels are right adjusted on tick mark (default is - centered) - -- `chopt = 'L'`: labels are left adjusted on tick mark. - -- `chopt = 'C'`: labels are centered on tick mark. - -- `chopt = 'M'`: In the Middle of the divisions. - -#### Label Formatting - -Blank characters are stripped, and then the label is correctly aligned. -The dot, if last character of the string, is also stripped. In the -following, we have some parameters, like tick marks length and -characters height (in percentage of the length of the axis, in user -coordinates). The default values are as follows: - -- Primary tick marks: 3.0 % - -- Secondary tick marks: 1.5 % - -- Third order tick marks: .75 % - -- Characters height for labels: 4% - -- Labels offset: 1.0 % - -#### Stripping Decimals - -Use the `TStyle::SetStripDecimals` to strip decimals when drawing axis -labels. By default, the option is set to true, and `TGaxis::PaintAxis` -removes trailing zeros after the dot in the axis labels, e.g. {0, 0.5, -1, 1.5, 2, 2.5, etc.} - -``` {.cpp} -TStyle::SetStripDecimals (Bool_t strip=kTRUE) -``` - -If this function is called with `strip=kFALSE`, `TGaxis::PaintAxis()` -will draw labels with the same number of digits after the dot, e.g. -{0.0, 0.5, 1.0, 1.5, 2.0, 2.5, etc.} - -#### Optional Grid - -`chopt = 'W'`: cross-Wire - -#### Axis Binning Optimization - -By default, the axis binning is optimized. - -- `chopt = 'N'`: No binning optimization - -- `chopt = 'I'`: Integer labeling - -### Axis with Time Units - - -Histograms' axis can be defined as "time axis". To do that it is enough -to activate the `SetTimeDisplay` attribute on a given axis. If `h` is a -histogram, it is done the following way: - -``` {.cpp} -h->GetXaxis()->SetTimeDisplay(1); // X axis is a time axis -``` - -Two parameters can be adjusted in order to define time axis: the time -format and the time offset. - -#### Time Format - -It defines the format of the labels along the time axis. It can be -changed using the **`TAxis`** method `SetTimeFormat`. The time format is -the one used by the C function `strftime()`. It is a string containing -the following formatting characters: - -+-----------------+----------------------------------------------------------+ -| For the date: | %a abbreviated weekday name | -| | | -| | %b abbreviated month name | -| | | -| | %d day of the month (01-31) | -| | | -| | %m month (01-12) | -| | | -| | %y year without century | -| | | -| | %Y year with century | -+-----------------+----------------------------------------------------------+ -| For the time: | %H hour (24-hour clock) | -| | | -| | %I hour (12-hour clock) | -| | | -| | %p local equivalent of AM or PM | -| | | -| | %M minute (00-59) | -| | | -| | %S seconds (00-61) | -| | | -| | %% % | -+-----------------+----------------------------------------------------------+ - -The other characters are output as is. For example to have a format like -`dd/mm/yyyy` one should do: - -``` {.cpp} -h->GetXaxis()->SetTimeFormat("%d/%m/%Y"); -``` - -If the time format is not defined, a default one will be computed -automatically. - -#### Time Offset - -This is a time in seconds in the UNIX standard UTC format (the universal -time, not the local one), defining the starting date of a histogram -axis. This date should be greater than 01/01/95 and is given in seconds. -There are three ways to define the time offset: - -1- By setting the global default time offset: - -``` {.cpp} -TDatime da(2003,02,28,12,00,00); -gStyle->SetTimeOffset(da.Convert()); -``` - -If no time offset is defined for a particular axis, the default time -offset will be used. In the example above, notice the usage of -**`TDatime`** to translate an explicit date into the time in seconds -required by `SetTimeFormat`. - -2- By setting a time offset to a particular axis: - -``` {.cpp} -TDatime dh(2001,09,23,15,00,00); -h->GetXaxis()->SetTimeOffset(dh.Convert()); -``` - -3- Together with the time format using `SetTimeFormat`. The time offset -can be specified using the control character %F after the normal time -format. `%F` is followed by the date in the format: -`yyyy-mm-dd hh:mm:ss`. - -``` {.cpp} -h->GetXaxis()->SetTimeFormat("%d/%m/%y%F2000-02-28 13:00:01"); -``` - -Notice that this date format is the same used by the **`TDatime`** -function `AsSQLString`. If needed, this function can be used to -translate a time in seconds into a character string which can be -appended after `%F`. If the time format is not specified (before `%F`) -the automatic one will be used. The following example illustrates the -various possibilities. - -``` {.cpp} -{ - gStyle->SetTitleH(0.08); - TDatime da(2003,02,28,12,00,00); - gStyle->SetTimeOffset(da.Convert()); - ct = new TCanvas("ct","Time on axis",0,0,600,600); - ct->Divide(1,3); - ht1 = new TH1F("ht1","ht1",30000,0.,200000.); - ht2 = new TH1F("ht2","ht2",30000,0.,200000.); - ht3 = new TH1F("ht3","ht3",30000,0.,200000.); - for (Int_t i=1;i<30000;i++) { - Float_t noise = gRandom->Gaus(0,120); - ht1->SetBinContent(i,noise); - ht2->SetBinContent(i,noise*noise); - ht3->SetBinContent(i,noise*noise*noise); - } - ct->cd(1); - ht1->GetXaxis()->SetLabelSize(0.06); - ht1->GetXaxis()->SetTimeDisplay(1); - ht1->GetXaxis()->SetTimeFormat("%d/%m/%y%F2000-02-2813:00:01"); - ht1->Draw(); - ct->cd(2); - ht2->GetXaxis()->SetLabelSize(0.06); - ht2->GetXaxis()->SetTimeDisplay(1); - ht2->GetXaxis()->SetTimeFormat("%d/%m/%y"); - ht2->Draw(); - ct->cd(3); - ht3->GetXaxis()->SetLabelSize(0.06); - TDatime dh(2001,09,23,15,00,00); - ht3->GetXaxis()->SetTimeDisplay(1); - ht3->GetXaxis()->SetTimeOffset(dh.Convert()); - ht3->Draw(); -} -``` - -The output is shown in the figure below. If a time axis has no specified -time offset, the global time offset will be stored in the axis data -structure. The histogram limits are in seconds. If `wmin` and `wmax` are -the histogram limits, the time axis will spread around the time offset -value from `TimeOffset+wmin` to `TimeOffset+wmax`. Until now all -examples had a lowest value equal to 0. The following example -demonstrates how to define the histogram limits relatively to the time -offset value. - -![Time axis examples](pictures/030000C8.png) - -``` {.cpp} -{ - // Define the time offset as 2003, January 1st - TDatime T0(2003,01,01,00,00,00); - int X0 = T0.Convert(); - gStyle->SetTimeOffset(X0); - - // Define the lowest histogram limit as 2002,September 23rd - TDatime T1(2002,09,23,00,00,00); - int X1 = T1.Convert()-X0; - - // Define the highest histogram limit as 2003, March 7th - TDatime T2(2003,03,07,00,00,00); - int X2 = T2.Convert(1)-X0; - - TH1F * h1 = new TH1F("h1","test",100,X1,X2); - - TRandom r; - for (Int_t i=0;i<30000;i++) { - Double_t noise = r.Gaus(0.5*(X1+X2),0.1*(X2-X1)); - h1->Fill(noise); - } - - h1->GetXaxis()->SetTimeDisplay(1); - h1->GetXaxis()->SetLabelSize(0.03); - h1->GetXaxis()->SetTimeFormat("%Y/%m/%d"); - h1->Draw(); -} -``` - -The output is shown in the next figure. Usually time axes are created -automatically via histograms, but one may also want to draw a time axis -outside a "histogram context". Therefore, it is useful to understand how -**`TGaxis`** works for such axis. The time offset can be defined using -one of the three methods described before. The time axis will spread -around the time offset value. Actually, it will go from -`TimeOffset+wmin` to `TimeOffset+wmax` where `wmin` and `wmax` are the -minimum and maximum values (in seconds) of the axis. Let us take again -an example. Having defined "2003, February 28 at 12h", we would like to -see the axis a day before and a day after. - -![A histogram with time axis X](pictures/030000C9.png) - -A **`TGaxis`** can be created the following way (a day has 86400 -seconds): - -``` {.cpp} -TGaxis *axis = new TGaxis(x1,y1,x2,y2,-100000,150000,2405,"t"); -``` - -the "`t`" option (in lower case) means it is a "time axis". The axis -goes form 100000 seconds before `TimeOffset` and 150000 seconds after. -So the complete macro is: - -``` {.cpp} -{ - c1 = new TCanvas("c1","Examples of TGaxis",10,10,700,500); - c1->Range(-10,-1,10,1); - TGaxis *axis = new TGaxis(-8,-0.6,8,-0.6,-100000,150000,2405,"t"); - axis->SetLabelSize(0.03); - - TDatime da(2003,02,28,12,00,00); - axis->SetTimeOffset(da.Convert()); - axis->SetTimeFormat("%d/%m/%Y"); - axis->Draw(); -} -``` - -The time format is specified with: - -``` {.cpp} -axis->SetTimeFormat("%d/%m/%Y"); -``` - -The macro gives the following output: - -![](pictures/030000CA.png) - -Thanks to the **`TLatex`** directive `#splitline` it is possible to -write the time labels on two lines. In the previous example changing the -`SetTimeFormat` line by: - -``` {.cpp} -axis->SetLabelOffset(0.02); -axis->SetTimeFormat("#splitline{%Y}{%d/%m}"); -``` - -will produce the following axis: - -![](pictures/030000CB.png) - -### Axis Examples - - -To illustrate what was said, we provide two scripts. The first one -creates the picture shown in the next figure. - -![The first axis example](pictures/030000CC.png) - -The first script is: - -``` {.cpp} -{ - c1 = new TCanvas("c1","Examples of Gaxis",10,10,700,500); - c1->Range(-10,-1,10,1); - - TGaxis *axis1 = new TGaxis(-4.5,-0.2,5.5,-0.2,-6,8,510,""); - axis1->SetName("axis1"); - axis1->Draw(); - TGaxis *axis2 = new TGaxis(4.5,0.2,5.5,0.2,0.001,10000,510,"G"); - axis2->SetName("axis2"); - axis2->Draw(); - - TGaxis *axis3 = new TGaxis(-9,-0.8,-9,0.8,-8,8,50510,""); - axis3->SetName("axis3"); - axis3->Draw(); - TGaxis *axis4 = new TGaxis(-7,-0.8,7,0.8,1,10000,50510,"G"); - axis4->SetName("axis4"); - axis4->Draw(); - - TGaxis *axis5 = new TGaxis(-4.5,-6,5.5,-6,1.2,1.32,80506,"-+"); - axis5->SetName("axis5"); - axis5->SetLabelSize(0.03); - axis5->SetTextFont(72); - axis5->SetLabelOffset(0.025); - axis5->Draw(); - - TGaxis *axis6 = new TGaxis(-4.5,0.6,5.5,0.6,100,900,50510,"-"); - axis6->SetName("axis6"); - axis6->Draw(); - TGaxis *axis7 = new TGaxis(8,-0.8,8,0.8,0,9000,50510,"+L"); - axis7->SetName("axis7"); - axis7->SetLabelOffset(0.01); - axis7->Draw(); - - // One can make a vertical axis going top->bottom. - // However one need to adjust labels align to avoid overlapping. - TGaxis *axis8 = new TGaxis(6.5,0.8,6.5,-0.8,0,90,50510,"-L"); - axis8->SetName("axis8"); - axis8->Draw(); -} -``` - -![The second axis example](pictures/030000CD.png) - -The second example shows the use of the second form of the constructor, -with axis ticks position determined by a function **`TF1`**: - -``` {.cpp} -void gaxis3a() -{ - gStyle->SetOptStat(0); - - TH2F *h2 = new TH2F("h","Axes",2,0,10,2,-2,2); - h2->Draw(); - TF1 *f1=new TF1("f1","-x",-10,10); - TGaxis *A1 = new TGaxis(0,2,10,2,"f1",510,"-"); - A1->SetTitle("axis with decreasing values"); - A1->Draw(); - - TF1 *f2=new TF1("f2","exp(x)",0,2); - TGaxis *A2 = new TGaxis(1,1,9,1,"f2"); - A2->SetTitle("exponential axis"); - A2->SetLabelSize(0.03); - A2->SetTitleSize(0.03); - A2->SetTitleOffset(1.2); - A2->Draw(); - - TF1 *f3=new TF1("f3","log10(x)",0,800); - TGaxis *A3 = new TGaxis(2,-2,2,0,"f3",505); - A3->SetTitle("logarithmic axis"); - A3->SetLabelSize(0.03); - A3->SetTitleSize(0.03); - A3->SetTitleOffset(1.2); - A3->Draw(); -} -``` - -![An axis example with time display](pictures/030000CE.png) - -``` {.cpp} -// strip chart example -void seism() { - - TStopwatch sw; sw.Start(); - //set time offset - TDatime dtime; - gStyle->SetTimeOffset(dtime.Convert()); - TCanvas *c1 = new TCanvas("c1","Time on axis",10,10,1000,500); - c1->SetFillColor(42); - c1->SetFrameFillColor(33); - c1->SetGrid(); - - Float_t bintime = 1; - // one bin = 1 second. change it to set the time scale - TH1F *ht = new TH1F("ht","The ROOT seism",10,0,10*bintime); - Float_t signal = 1000; - ht->SetMaximum(signal); - ht->SetMinimum(-signal); - ht->SetStats(0); - ht->SetLineColor(2); - ht->GetXaxis()->SetTimeDisplay(1); - ht->GetYaxis()->SetNdivisions(520); - ht->Draw(); - - for (Int_t i=1;i<2300;i++) { - // Build a signal : noisy damped sine - Float_t noise = gRandom->Gaus(0,120); - if (i > 700) - noise += signal*sin((i-700.)*6.28/30)*exp((700.-i)/300.); - ht->SetBinContent(i,noise); - c1->Modified(); - c1->Update(); - gSystem->ProcessEvents(); - //canvas can be edited during the loop - } - printf("Real Time = %8.3fs,Cpu Time = %8.3fsn",sw.RealTime(), - sw.CpuTime()); -} -``` - -## Graphical Objects Attributes - - -### Text Attributes - - -When a class contains text or derives from a text class, it needs to be -able to set text attributes like font type, size, and color. To do so, -the class inherits from the **`TAttText`** class (a secondary -inheritance), which defines text attributes. **`TLatex`** and -**`TText`** inherit from **`TAttText`**. - -#### Setting Text Alignment - -Text alignment may be set by a method call. What is said here applies to -all objects deriving from **`TAttText`**, and there are many. We will -take an example that may be transposed to other types. Suppose "`la`" is -a **`TLatex`** object. The alignment is set with: - -``` {.cpp} -root[] la->SetTextAlign(align) -``` - -The parameter `align` is a `short` describing the alignment: - -`align = 10*HorizontalAlign + VerticalAlign` - -For horizontal alignment, the following convention applies: - -- 1 = left - -- 2 = centered - -- 3 = right - -For vertical alignment, the following convention applies: - -- 1 = bottom - -- 2 = centered - -- 3 = top - -For example, align: 11 = left adjusted and bottom adjusted; 32 = right -adjusted and vertically centered. - -#### Setting Text Angle - -Use `TAttText::SetTextAngle` to set the text angle. The `angle` is the -degrees of the horizontal. - -``` {.cpp} -root[] la->SetTextAngle(angle) -``` - -#### Setting Text Color - -Use `TAttText::SetTextColor` to set the text color. The `color` is the -color index. The colors are described in "Color and Color Palettes". - -``` {.cpp} -root[] la->SetTextColor(color) -``` - -#### Setting Text Font - -Use `TAttText::SetTextFont` to set the font. The parameter font is the -font code, combining the font and precision: -`font = 10 * fontID + precision` - -``` {.cpp} -root[] la->SetTextFont(font) -``` - -The table below lists the available fonts. The font IDs must be between -1 and 14. The precision can be: - -- Precision = 0 fast hardware fonts (steps in the size) - -- Precision = 1 scalable and rotate-able hardware fonts (see below) - -- Precision = 2 scalable and rotate-able hardware fonts - -When precision 0 is used, only the original non-scaled system fonts are -used. The fonts have a minimum (4) and maximum (37) size in pixels. -These fonts are fast and are of good quality. Their size varies with -large steps and they cannot be rotated. Precision 1 and 2 fonts have a -different behavior depending if True Type Fonts (TTF) are used or not. -If TTF are used, you always get very good quality scalable and -rotate-able fonts. However, TTF are slow. Precision 1 and 2 fonts have a -different behavior for PostScript in case of **`TLatex`** objects: - -- With precision 1, the PostScript text uses the old convention (see - **`TPostScript`**) for some special characters to draw sub and - superscripts or Greek text. - -- With precision 2, the "PostScript" special characters are drawn as - such. To draw sub and superscripts it is highly recommended to use - **`TLatex`** objects instead. - -For example: `font = 62` is the font with ID `6` and precision `2`. - -![Font's examples](pictures/030000CF.png) - -The available fonts are: - -+-----------+--------------------------+-----------------------+---------+------------+ -| Font ID | X11 | True Type name | Is | "boldness" | -| | | | italic | | -+-----------+--------------------------+-----------------------+---------+------------+ -| 1 | times-medium-i-normal | "Times New Roman" | Yes | 4 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 2 | times-bold-r-normal | "Times New Roman" | No | 7 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 3 | times-bold-i-normal | "Times New Roman" | Yes | 7 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 4 | helvetica-medium-r-norma | "Arial" | No | 4 | -| | l | | | | -+-----------+--------------------------+-----------------------+---------+------------+ -| 5 | helvetica-medium-o-norma | "Arial" | Yes | 4 | -| | l | | | | -+-----------+--------------------------+-----------------------+---------+------------+ -| 6 | helvetica-bold-r-normal | "Arial" | No | 7 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 7 | helvetica-bold-o-normal | "Arial" | Yes | 7 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 8 | courier-medium-r-normal | "Courier New" | No | 4 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 9 | courier-medium-o-normal | "Courier New" | Yes | 4 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 10 | courier-bold-r-normal | "Courier New" | No | 7 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 11 | courier-bold-o-normal | "Courier New" | Yes | 7 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 12 | symbol-medium-r-normal | "Symbol" | No | 6 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 13 | times-medium-r-normal | "Times New Roman" | No | 4 | -+-----------+--------------------------+-----------------------+---------+------------+ -| 14 | | "Wingdings" | No | 4 | -+-----------+--------------------------+-----------------------+---------+------------+ - -This script makes the image of the different fonts: - -``` {.cpp} -{ - textc = new TCanvas("textc","Example of text",1); - for (int i=1;i<15;i++) { - cid = new char[8]; - sprintf(cid,"ID %d :",i); - cid[7] = 0; - lid = new TLatex(0.1,1-(double)i/15,cid); - lid->SetTextFont(62); - lid->Draw(); - l = new TLatex(.2,1-(double)i/15, - "The quick brown fox is not here anymore") - l->SetTextFont(i*10+2); - l->Draw(); - } -} -``` - -#### How to use True Type Fonts - -You can activate the True Type Fonts by adding the following line in -your `.rootrc` file. - -``` {.cpp} -Unix.*.Root.UseTTFonts: true -``` - -You can check that you indeed use the `TTF` in your Root session. When -the `TTF` is active, you get the following message at the start of a -session: "Free Type Engine v1.x used to render TrueType fonts." You can -also check with the command: - -``` {.cpp} -gEnv->Print() -``` - -#### Setting Text Size - -Use `TAttText::SetTextSize` to set the text size. - -``` {.cpp} -root[] la->SetTextSize(size) -``` - -The `size` is the text size expressed in percentage of the current pad -size. - -The text size in pixels will be: - -- If current pad is horizontal, the size in pixels = - `textsize * canvas_height` - -- If current pad is vertical, the size in pixels = - `textsize * canvas_width` - -![](pictures/030000D0.png) The user interface for changing the text -color, size, font and alignment looks like shown in this picture. It -takes place in the editor frame anytime the selected object inherits the -class **`TAttText`**. - -### Line Attributes - - -All classes manipulating lines have to deal with line attributes: color, -style and width. This is done by using secondary inheritance of the -class **`TAttLine`**. The line color may be set by a method call. What -is said here applies to all objects deriving from **`TAttLine`**, and -there are many (histograms, plots). We will take an example that may be -transposed to other types. Suppose "`li`" is a **`TLine`** object. The -line color is set with: - -``` {.cpp} -root[] li->SetLineColor(color) -``` - -The argument `color` is a color number. The colors are described in -"Color and Color Palettes" - -The line style may be set by a method call. What is said here applies to -all objects deriving from **`TAttLine`**, and there are many -(histograms, plots). We will take an example that may be transposed to -other types. Suppose "`li`" is a **`TLine`** object. The line style is -set with: - -``` {.cpp} -root[] li->SetLineStyle(style) -``` - -The argument style is one of: 1=solid, 2=dash, 3=dot, 4=dash-dot. - -The line width may be set by a method call. What is said here applies to -all objects deriving from **`TAttLine`**, and there are many -(histograms, plots). We will take an example that may be transposed to -other types. Suppose "`li`" is a **`TLine`** object. The line width is -set with: - -``` {.cpp} -root[] li->SetLineWidth(width) -``` - -The `width` is the width expressed in pixel units. - -![](pictures/030000D1.png) The user interface for changing the line -color, line width and style looks like shown in this picture. It takes -place in the editor frame anytime the selected object inherits the class -**`TAttLine`**. - -### Fill Attributes - - -Almost all graphics classes have a fill area somewhere. These classes -have to deal with fill attributes. This is done by using secondary -inheritance of the class **`TAttFill`**. Fill color may be set by a -method call. What is said here applies to all objects deriving from -**`TAttFill`**, and there are many (histograms, plots). We will take an -example that may be transposed to other types. Suppose "`h`" is a -**`TH1F`** (1 dim histogram) object. The histogram fill color is set -with: - -``` {.cpp} -root[] h->SetFillColor(color) -``` - -The color is a color number. The colors are described in "Color and -color palettes" - -Fill style may be set by a method call. What is said here applies to all -objects deriving from `TAttFill`, and there are many (histograms, -plots). We will take an example that may be transposed to other types. -Suppose "`h`" is a **TH1F** (1 dim histogram) object. The histogram fill -style is set with: - -``` {.cpp} -root[] h->SetFillStyle(style) -``` - -The convention for style is: 0:hollow, 1001:solid, 2001:hatch style, -3000+pattern number:patterns, 4000 to 4100:transparency, 4000:fully -transparent, 4100: fully opaque. - -Fill styles \>3100 and \<3999 are hatches. They are defined according to -the `FillStyle=3ijk` value as follows: - -- `i(1-9)` specifies the space between each hatch `(1=minimum space`, - `9=maximum)`. The final spacing is set by `SetHatchesSpacing()` - method and it is`*GetHatchesSpacing()`. - -- `j(0-9)` specifies the angle between 0 and 90 degres as follows: - `0=0`, `1=10`, `2=20`, `3=30`, `4=45`, `5=not drawn`, `6=60`, - `7=70`, `8=80` and `9=90`. - -- `k(0-9)` specifies the angle between 0 and 90 degres as follows: - `0=180`, `1=170`, `2=160`, `3=150`, `4=135`, `5=not drawn`, `6=120`, - `7=110`, `8=100` and `9=90`. - -![The various patterns](pictures/030000D2.png) - -### Color and Color Palettes - - -At initialization time, a table of basic colors is generated when the -first Canvas constructor is called. This table is a linked list, which -can be accessed from the ***`gROOT`*** object (see -`TROOT::GetListOfColors()`). Each color has an index and when a basic -color is defined, two "companion" colors are defined: the dark version and the bright version. -Two static functions are available that return the bright or dark color number corresponding -to a given color index. If these variants don't already exist, they are created as needed: -``` - Int_t dark = TColor::GetColorDark(color_index); - Int_t bright = TColor::GetColorBright(color_index); -``` - -The dark and bright colors are used to give 3-D effects when drawing -various boxes (see **`TWbox`**, **`TPave`**, **`TPaveText`**, -**`TPaveLabel`**, etc). If you have a black and white copy of the -manual, here are the basic colors and their indices. - -![The basic ROOT colors](pictures/030000D3.png) - -![](pictures/image212.jpg) - -The list of currently supported basic colors (here dark and bright -colors are not shown) are shown. The color numbers specified in the -basic palette, and the picture above, can be viewed by selecting the -menu entry Colors in the View canvas menu. The user may define other -colors. To do this, one has to build a new **`TColor`**: - -``` {.cpp} -TColor(Int_t color,Float_t r,Float_t g,Float_t b,const char* name) -``` - -One has to give the color number and the three Red, Green, Blue values, -each being defined from 0 (min) to 1(max). An optional name may be -given. When built, this color is automatically added to the existing -list of colors. If the color number already exists, one has to extract -it from the list and redefine the RGB values. This may be done for -example with: - -``` {.cpp} -root[] color=(TColor*)(gROOT->GetListOfColors()->At(index_color)) -root[] color->SetRGB(r,g,b) -``` - -Where `r`, `g` and `b` go from 0 to 1 and `index_color` is the color -number you wish to change. - -![](pictures/030000D4.png) The user interface for changing the fill -color and style looks like shown in this picture. It takes place in the -editor frame anytime the selected object inherits the class -**`TAttFill`**. - -#### Color Palette (for Histograms) - -Defining one color at a time may be tedious. The histogram classes (see -Draw Options) use the color palette. For example, `TH1::Draw("col")` -draws a 2-D histogram with cells represented by a box filled with a -color `CI` function of the cell content. If the cell content is `N`, the -color `CI` used will be the color number in `colors[N]`. If the maximum -cell content is `>ncolors`, all cell contents are scaled to `ncolors`. -The current color palette does not have a class or global object of its -own. It is defined in the current style as an array of color numbers. -The current palette can be changed with: - -``` {.cpp} -TStyle::SetPalette(Int_t ncolors,Int_t*color_indexes). -``` - -By default, or if `ncolors <= 0`, a default palette (see above) of 50 -colors is defined. The colors defined in this palette are good for -coloring pads, labels, and other graphic objects. If `ncolors > 0` and -`colors = 0`, the default palette is used with a maximum of `ncolors`. -If `ncolors == 1 && colors == 0`, then a pretty palette with a spectrum -`Violet->Red` is created. It is recommended to use this pretty palette -when drawing lego(s), surfaces or contours. For example, to set the -current palette to the "`pretty`" one, do: - -``` {.cpp} -root[] gStyle->SetPalette(1) -``` - -A more complete example is shown below. It illustrates the definition of -a custom palette. You can adapt it to suit your needs. In case you use -it for contour coloring, with the current color/contour algorithm, -always define two more colors than the number of contours. - -``` {.cpp} -void palette() { - // Example of creating new colors (purples) - const Int_t colNum = 10; // and defining of a new palette - Int_t palette[colNum]; - for (Int_t i=0; iGetColor(230+i) ){ - TColor *color = - new TColor(230+i,1-(i/((colNum)*1.0)),0.3,0.5,""); - } else { - TColor *color = gROOT->GetColor(230+i); - color->SetRGB(1-(i/((colNum)*1.0)),0.3,0.5); - } - palette[i] = 230+i; - } - gStyle->SetPalette(colNum,palette); - TF2 *f2 = new TF2("f2","exp(-(x^2)-(y^2))",-3,3,-3,3); - // two contours less than the number of colors in palette - f2->SetContour(colNum-2); - f2->Draw("cont"); -} -``` - -Since ROOT 6.26, you can also define a palette based on an ASCII text -file, using `TColor::CreateColorTableFromFile("filename.txt")` or -`gStyle->SetPalette("filename.txt")`. The input file contains one color -per line in "r g b" float format. This function is useful to profit from -a full set of colour-vision deficiency friendly and perceptually uniform -colour maps that are available to -[download](https://doi.org/10.5281/zenodo.4491293) - -## The Graphics Editor - - -A new graphics editor took place in ROOT v4.0. The editor can be -activated by selecting the Editor menu entry in the canvas View menu or -one of the context menu entries for setting line, fill, marker or text -attributes. The following object editors are available for the current -ROOT version. - -### TAxisEditor - - -![](pictures/030000D5.png) - -This user interface gives the possibility for changing the following -axis attributes: - -- color of the selected axis, the axis' title and labels; - -- the length of thick parameters and the possibility to set them on - both axis sides (if `+-` is selected); - -- to set logarithmic or linear scale along the selected axis with a - choice for optimized or more logarithmic labels; - -- primary, secondary and tertiary axis divisions can be set via the - three number fields; - -- the axis title can be added or edited and the title's color, - position, offset, size and font can be set interactively; - -- the color, size, and offset of axis labels can be set similarly. In - addition, there is a check box for no exponent choice, and another - one for setting the same decimal part for all labels. - -### TPadEditor - - -![](pictures/030000D6.png) - -- It provides the following user interface: - -- Fixed aspect ratio - can be set for pad resizing. - -- Edit - sets pad or canvas as editable. - -- Cross-hair - sets a cross hair on the pad. - -- TickX - set ticks along the X axis. - -- TickY - set ticks along the Y axis. - -- GridX - set a grid along the X axis. - -- GridY - set a grid along the Y axis. - -- The pad or canvas border size can be set if a sunken or a raised - border mode is - -- selected; no border mode can be set too. - -## Copy and Paste - - -You can make a copy of a canvas using `TCanvas::DrawClonePad`. This -method is unique to **`TCanvas`**. It clones the entire canvas to the -active pad. There is a more general method `TObject::DrawClone`, which -all objects descendent of **`TObject`**, specifically all graphic -objects inherit. Below are two examples, one to show the use of -`DrawClonePad` and the other to show the use of `DrawClone`. - -### Using the GUI - - -In this example we will copy an entire canvas to a new one with -`DrawClonePad`. Run the script `draw2dopt.C`. - -``` {.cpp} -root[] .x tutorials/hist/draw2dopt.C -``` - -This creates a canvas with 2D histograms. To make a copy of the canvas -follow the steps: - -- Right-click on it to bring up the context menu - -- Select `DrawClonePad` - -This copies the entire canvas and all its sub-pads to a new canvas. The -copied canvas is a deep clone, and all the objects on it are copies and -independent of the original objects. For instance, change the fill on -one of the original histograms, and the cloned histogram retains its -attributes. `DrawClonePad` will copy the canvas to the active pad; the -target does not have to be a canvas. It can also be a pad on a canvas. - -![Different draw options](pictures/030000D7.png) - -If you want to copy and paste a graphic object from one canvas or pad to -another canvas or pad, you can do so with `DrawClone` method inherited -from **`TObject`**. All graphics objects inherit the -`TObject::DrawClone` method. In this example, we create a new canvas -with one histogram from each of the canvases from the script -`draw2dopt.C`. - -- Start a new ROOT session and execute the script `draw2dopt.C` - -- Select a canvas displayed by the script, and create a new canvas - `c1` from the File menu. - -- Make sure that the target canvas (`c1`) is the active one by middle - clicking on it. If you do this step right after step 2, c1 will be - active. - -- Select the pad with the first histogram you want to copy and paste. - -- Right click on it to show the context menu, and select `DrawClone`. - -- Leave the option blank and hit OK. - -Repeat these steps for one histogram on each of the canvases created by -the script, until you have one pad from each type. If you wanted to put -the same annotation on each of the sub pads in the new canvas, you could -use `DrawClone` to do so. Here we added the date to each pad. The steps -to this are: - -- Create the label in on of the pads with the graphics editor. - -- Middle-click on the target pad to make it the active pad - -- Use `DrawClone` method of the label to draw it in each of the other - panels. - -The option in the `DrawClone` method argument is the Draw option for a -histogram or graph. A call to `TH1::DrawClone` can clone the histogram -with a different draw option. - -### Programmatically - - -To copy and paste the four pads from the command line or in a script you -would execute the following statements: - -``` {.cpp} -root[] .x tutorials/hist/draw2dopt.C -root[] auto p1 = surfopt->GetPad(1); // get the first pad -root[] auto p2 = lego->GetPad(2); // get the second pad -root[] auto p3 = contours->GetPad(3); // get the third pad -root[] auto p4 = c2h->GetPad(4); // get the forth pad -root[] TCanvas c1("c1","Copy Paste",200,200,800,600); -root[] p1->DrawClone(); -root[] p2->DrawClone(); -root[] p3->DrawClone(); -root[] p4->DrawClone(); -``` - -Note that the pad is copied to the new canvas in the same location as in -the old canvas. For example if you were to copy the third pad of `surfopt` -canvas to the top left corner of the target canvas you would have to reset the -coordinates of the cloned pad. - -## Legends - - -Legends for a graph are obtained with a **`TLegend`** object. This -object points to markers, lines, boxes, histograms, graphs and represent -their marker, line, fill attributes. Any object that has a marker or -line or fill attribute may have an associated legend. A **`TLegend`** is -a panel with several entries (class **`TLegendEntry`**) and is created -by the constructor - -``` {.cpp} -TLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2, - const char *header, Option_t *option) -``` - -The legend is defined with default coordinates, border size and option. -The legend coordinates (NDC) in the current pad are `x1`, `y1`, `x2`, -`y2`. The default text attributes for the legend are: - -- Alignment = 12 left adjusted and vertically centered - -- Angle = 0 (degrees) - -- Color = 1 (black) - -- Size = calculate when number of entries is known - -- Font = helvetica-medium-r-normal scalable font = 42, and bold = 62 - for title - -The title is a regular entry and supports **`TLatex`**. The default is -no title (`header = 0`). The options are the same as for **`TPave`**; by -default, they are "`brand`". Once the legend box is created, one has to -add the text with the `AddEntry()` method: - -``` {.cpp} -TLegendEntry* TLegend::AddEntry(TObject *obj, - const char *label, - Option_t *option) -``` - -The parameters are: - -- `*obj `is a pointer to an object having marker, line, or fill - attributes (a histogram, or a graph) - -- `label` is the label to be associated to the object - -- `option`: - -- "L" draw line associated with line attributes of `obj`, if `obj` - inherits from **`TAttLine`**. - -- "P" draw poly-marker associated with marker attributes of `obj`, if - `obj` inherits **`TAttMarker`**. - -- "F" draw a box with fill associated with fill attributes of `obj`, - if `obj` inherits **`TAttFill`**. - -One may also use the other form of the method `AddEntry`: - -``` {.cpp} -TLegendEntry* TLegend::AddEntry(const char *name, - const char *label, - Option_t *option) -``` - -Here `name` is the name of the object in the pad. Other parameters are -as in the previous case. Next example shows how to create a legend: - -``` {.cpp} -leg = new TLegend(0.4,0.6,0.89,0.89); -leg->AddEntry(fun1,"One Theory","l"); -leg->AddEntry(fun3,"Another Theory","f"); -leg->AddEntry(gr,"The Data","p"); -leg->Draw(); -// oops we forgot the blue line... add it after -leg->AddEntry(fun2, - "#sqrt{2#pi} P_{T} (#gamma) latex formula","f"); -// and add a header (or "title") for the legend -leg->SetHeader("The Legend Title"); -leg->Draw(); -``` - -Here `fun1`, `fun2`, `fun3` and `gr` are pre-existing functions and -graphs. You can edit the **`TLegend`** by right clicking on it. - -![A legend example](pictures/030000D8.png) - -## The PostScript Interface - - -To generate a PostScript (or encapsulated PostScript) file for a single -image in a canvas, you can: - -- Select to print the canvas in the PostScript file format from the - File menu / Save or Save As menu entries. By default, a PostScript - file is generated, if you do not specify the file format. - -- Click in the canvas area, near the edges, with the right mouse - button and select the Print context menu entry. This will generate a - file of canvas pointed to by c1. You can select the name of the - PostScript file. If the file name is `xxx.ps`, you will generate a - PostScript file named `xxx.ps`. If the file name is `xxx.eps`, you - generate an encapsulated Postscript file instead. In your program - (or script), you can type: - -``` {.cpp} -c1->Print("xxx.ps") // or -c1->Print("xxx.eps") -``` - -Next example prints the picture in the pad pointed by `pad1`. - -``` {.cpp} -pad1->Print("xxx.ps") -``` - -The `TPad::Print` method has a second parameter called option. Its value -can be: - -- ` 0` which is the default and is the same as "`ps`" - -- "`ps`" a Postscript file is produced - -- "`Portrait`" a Postscript file is produced with Portrait orientation - -- "`Landscape`" a Postscript file is produced with Landscape orientation - -- "`eps`"an Encapsulated Postscript file - -- "`Preview`"an Encapsulated Postscript file with preview is produced - -- "`gif`" a Graphics Interchange Format file - -- "`cxx`" a C++ macro file is generated - -- "`pdf`"a Portable Document Format file - -- "`xml`" a eXtensible Mark-up Language file - -- "`jpg`"a Joint Photographic Experts Group file - -- "`png`" a Portable Network Graphics Format (PNG file) - -- "`xpm`" a X11 Pixel Map Format - -- "`svg`" a Scalable Vector Graphics file - -- "`tiff`" a Tagged-Image File Format - -- "`root`"a ROOT binary file is produced - -You do not need to specify this second parameter; you can indicate by -the filename extension what format you want to save a canvas in (i.e. -`canvas.ps`, `canvas.gif`, `canvas.C`, etc). - -The size of the PostScript picture, by default, is computed to keep the -aspect ratio of the picture on the screen, where the size along `x` is -always 20 cm. You can set the size of the PostScript picture before -generating the picture with a command such as: - -``` {.cpp} -TPostScript myps("myfile.ps",111) -myps.Range(xsize,ysize); -object->Draw(); -myps.Close(); -``` - -The first parameter in the **`TPostScript`** constructor is the name of -the file; the second one is the format option: - -- 111 - `ps portrait` - -- 112 - `ps landscape` - -- 113 - `eps` - -You can set the default paper size with: - -``` {.cpp} -gStyle->SetPaperSize(xsize,ysize); -``` - -You can resume writing again in this file with `myps.Open()`. Note that -you may have several Post Script files opened simultaneously. Use -`TPostScript::Text(x,y,"string")` to add text to a postscript file. This -method writes the string in quotes into a PostScript file at position -`x, y` in world coordinates. - -### Special Characters - - -The following characters have a special action on the PostScript file: - -- `` ` `` - go to Greek - -- `'` - go to special - -- `~` - go to Zapf Dingbats - -- `?` - go to subscript - -- `^` - go to superscript - -- `!` - go to normal level of script - -- `&` - backspace one character - -- `#` - end of Greek or end of ZapfDingbats - -These special characters are printed as such on the screen. To generate -one of these characters on the PostScript file, you must escape it with -the escape character "@". The use of these special characters is -illustrated in several scripts referenced by the **`TPostScript`** -constructor. - -### Writing Several Canvases to the Same PostScript File - - -The following sequence writes the canvas to "`c1.ps`" and closes the -postscript file: - -``` {.cpp} -TCanvas c1("c1"); -h1.Draw(); -c1.Print("c1.ps"); -``` - -If the Postscript file name finishes with "`(`", the file remains opened -(it is not closed). If the Postscript file name finishes with "`)`" and -the file has been opened with "`(`", the file is closed. - -``` {.cpp} -{ - TCanvas c1("c1"); - h1.Draw(); - c1.Print("c1.ps("); // write canvas and keep the ps file open - h2.Draw(); - c1.Print("c1.ps"); // canvas is added to "c1.ps" - h3.Draw(); - c1.Print("c1.ps)"); // canvas is added to "c1.ps" - // and ps file is closed -} -``` - -The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can be -a little inconvenient to have the action of opening/closing a file being -atomic with printing a page. Particularly if pages are being generated -in some loop, one needs to detect the special cases of first and last -page. The "`[`" and "`]`" can be used instead of "`(`" and "`)`" as -shown in the next example. - -``` {.cpp} -c1.Print("file.ps["); // no actual print; just open file.ps -for (i=0; i<10; ++i) { - // fill canvas for context i - ... - c1.Print("file.ps"); // actually print canvas to file.ps -} // end loop -c1.Print("file.ps]"); // no actual print; just close file.ps -``` - -The following script illustrates how to open a postscript file and draw -several pictures. The generation of a new postscript page is automatic -when **`TCanvas::Clear` is called by `object->Draw()`.** - -``` {.cpp} -{ - TFile f("hsimple.root"); - TCanvas c1("c1","canvas",800,600); - - //select PostScript output type - Int_t type = 111; //portrait ps - // Int_t type = 112; //landscape ps - // Int_t type = 113; //eps - - //create a PostScript file and set the paper size - TPostScript ps("test.ps",type); - ps.Range(16,24); //set x,y of printed page - - //draw 3 histograms from file hsimple.root on separate pages - hpx->Draw(); - c1.Update(); //force drawing in a script - hprof->Draw(); - c1.Update(); - hpx->Draw("lego1"); - c1.Update(); - ps.Close(); -} -``` - -The next example does the same: - -``` {.cpp} -{ - TFile f("hsimple.root"); - TCanvas c1("c1","canvas",800,600); - - //set x,y of printed page - gStyle->SetPaperSize(16,24); - - //draw 3 histograms from file hsimple.root on separate pages - hpx->Draw(); - c1->Print("test1.ps(", "Portrait"); - hprof->Draw(); - c1->Print("test1.ps"); - hpx->Draw("lego1"); - c1->Print("test1.ps)"); -} -``` - -This following example shows two pages. The canvas is divided. -`TPostScript::NewPage` must be called before starting a new picture. -`object->Draw` does not clear the canvas in this case because we clear -only the pads and not the main canvas. Note that `c1->Update` must be -called at the end of the first picture. - -``` {.cpp} -{ - TFile *f1 = new TFile("hsimple.root"); - TCanvas *c1 = new TCanvas("c1"); - TPostScript *ps = new TPostScript("file.ps",112); - - // picture 1 - c1->Divide(2,1); - ps->NewPage(); - c1->cd(1); - hpx->Draw(); - c1->cd(2); - hprof->Draw(); - - // picture 2 - c1->Update(); - ps->NewPage(); - c1->cd(1); - hpxpy->Draw(); - c1->cd(2); - ntuple->Draw("px"); - c1->Update(); - ps->Close(); - - // invoke PostScript viewer - gSystem->Exec("gs file.ps"); -} -``` - -The next one does the same: - -``` {.cpp} -{ - TFile *f1 = new TFile("hsimple.root"); - TCanvas *c1 = new TCanvas("c1"); - c1->Divide(2,1); - - // picture 1 - c1->cd(1); - hpx->Draw(); - c1->cd(2); - hprof->Draw(); - c1->Print("test2.ps(", "Landscape"); - - // picture 2 - c1->cd(1); - hpxpy->Draw(); - c1->cd(2); - ntuple->Draw("px"); - c1->Print("test2.ps)"); - gSystem->Exec("gs file.ps"); // invoke PostScript viewer -} -``` -### The Color Models - -`TPostScript` (and `TPDF`) support two color models: RGB and CMYK. -CMY and CMYK models are subtractive color models unlike RGB which is an -additive. They are mainly used for printing purposes. CMY means Cyan -Magenta Yellow to convert RGB to CMY it is enough to do: -`C=1-R`, `M=1-G` and `Y=1-B`. CMYK has one more component K -(black). The conversion from RGB to CMYK is: - -``` {.cpp} - Double_t Black = TMath::Min(TMath::Min(1-Red,1-Green),1-Blue); - Double_t Cyan = (1-Red-Black)/(1-Black); - Double_t Magenta = (1-Green-Black)/(1-Black); - Double_t Yellow = (1-Blue-Black)/(1-Black); -``` - -``CMYK`` add the black component which allows to have a better quality -for black printing. `TPostScript` (and `TPDF`) support the ``CMYK`` model. -To change the color model use: - -``` {.cpp} - gStyle->SetColorModelPS(c); -``` - -- `c = 0` means TPostScript will use RGB color model (default) -- `c = 1` means TPostScript will use CMYK color model - -## The PDF Interface - -Like PostScript, PDF is a vector graphics output format allowing a very -high graphics output quality. The functionalities provided by this class -are very similar to those provided by `TPostScript`. - -Compare to PostScript output, the PDF files are usually smaller because -some parts of them can be compressed. - -PDF also allows to define table of contents. This facility can be used -in ROOT. The following example shows how to proceed: - -``` {.cpp} -{ - TCanvas* canvas = new TCanvas("canvas"); - TH1F* histo = new TH1F("histo","test 1",10,0.,10.); - histo->SetFillColor(2); - histo->Fill(2.); - histo->Draw(); - canvas->Print("plots.pdf(","Title:One bin filled"); - histo->Fill(4.); - histo->Draw(); - canvas->Print("plots.pdf","Title:Two bins filled"); - histo->Fill(6.); - histo->Draw(); - canvas->Print("plots.pdf","Title:Three bins filled"); - histo->Fill(8.); - histo->Draw(); - canvas->Print("plots.pdf","Title:Four bins filled"); - histo->Fill(8.); - histo->Draw(); - canvas->Print("plots.pdf)","Title:The fourth bin content is 2"); -} -``` - -Each character string following the keyword "Title:" makes a new entry -in the table of contents. - -## Create or Modify a Style - - -All objects that can be drawn in a pad inherit from one or more -attribute classes like **`TAttLine`**, **`TAttFill`**, **`TAttText`**, -**`TAttMarker`**. When objects are created, their default attributes are -taken from the current style. The current style is an object of the -class **`TStyle`** and can be referenced via the global variable -***`gStyle`*** (in `TStyle.h`). See the class **`TStyle`** for a -complete list of the attributes that can be set in one style. - -ROOT provides several styles called: - -- "`Default`" - the default style - -- "`Plain`" - the simple style (black and white) - -- "`Bold`" - bolder lines - -- "`Video`" - suitable for html output or screen viewing - -The "`Default`" style is created by: - -``` {.cpp} -TStyle *default = new TStyle("Default","Default Style"); -``` - -The "`Plain`" style can be used if you want to get a "conventional" -PostScript output or if you are working on a monochrome display. The -following example shows how to create it. - -``` {.cpp} -TStyle *plain = new TStyle("Plain", - "Plain Style(no colors/fill areas)"); -plain->SetCanvasBorderMode(0); -plain->SetPadBorderMode(0); -plain->SetPadColor(0); -plain->SetCanvasColor(0); -plain->SetTitleColor(0); -plain->SetStatColor(0); -``` - -You can set the current style by: - -``` {.cpp} -gROOT->SetStyle(style_name); -``` - -You can get a pointer to an existing style by: - -``` {.cpp} -TStyle *style = gROOT->GetStyle(style_name); -``` - -You can create additional styles by: - -``` {.cpp} -TStyle *st1 = new TStyle("st1","my style"); -st1->Set... -st1->cd(); // this becomes now the current style gStyle -``` - -In your `rootlogon.C` file, you can redefine the default parameters via -statements like: - -``` {.cpp} -gStyle->SetStatX(0.7); -gStyle->SetStatW(0.2); -gStyle->SetLabelOffset(1.2); -gStyle->SetLabelFont(72); -``` - -Note that when an object is created, its attributes are taken from the -current style. For example, you may have created a histogram in a -previous session and saved it in a file. Meanwhile, if you have changed -the style, the histogram will be drawn with the old attributes. You can -force the current style attributes to be set when you read an object -from a file by calling `ForceStyle` before reading the objects from the -file. - -``` {.cpp} -gROOT->ForceStyle(); -``` - -When you call `gROOT->ForceStyle()` and read an object from a ROOT file, -the object's method `UseCurrentStyle` is called. The attributes saved -with the object are replaced by the current style attributes. You call -also call `myObject->UseCurrentStyle()` directly. For example if you -have a canvas or pad with your histogram or any other object, you can -force these objects to get the attributes of the current style by: - -``` {.cpp} -canvas->UseCurrentStyle(); -``` - -The description of the style functions should be clear from the name of -the **`TStyle`** setters or getters. Some functions have an extended -description, in particular: - -- `TStyle::SetLabelFont` - -- `TStyle::SetLineStyleString`: set the format of dashed lines. - -- `TStyle::SetOptStat` - -- `TStyle::SetPalette` to change the colors palette - -- `TStyle::SetTitleOffset` - -- `TStyle::SetOptDate(Int_t optdate)` to support several date formats. - If `optdate` is non-null, the current date/time will be printed in - the canvas. The position of the date string can be controlled by: - `optdate = 10*format `+` mode` - -- `mode = 1` the date is printed in the bottom/left corner - -- `mode = 2` date is printed in the bottom/right corner - -- `mode = 3` date is printed in the top/right corner - -- `format = 0` (default) date format is like: "Wed Sep 25 17:10:35 - 2002" - -- `format = 1` date format is: "2002-09-25" - -- `format = 2` date format is: "2002-09-25 17:10:35" - -## 3D Viewers - - -ROOT provides several viewers capable of displaying 3D content: - -- the Pad - simple line drawing using **`TPad`** and associated - projection class **`TView`**; - -- GL Viewer - high quality and performance viewer(See "The GL - Viewer"); - -- X3D viewer - simple legacy viewer (See "The X3D Viewer"); - -- GL-in-pad - combination of basic GL viewer in **`TPad`**, with no - hardware acceleration. - -The X3D and GL viewers are created as external windows, associated with -a pad, and displaying the same content as it. Only these external -viewers are detailed here - for Pad (**`TPad`**, **`TView`** classes) -you should refer to "Graphical Containers: Canvas and Pad" and the class -definitions. - -All viewers use a common architecture to publish 3D objects to the -viewer - described in "Common 3D Viewer Architecture" below. In most -cases, you will **not** need to use this, working instead with a -package, such as the "The Geometry Package", which provides -comprehensive, high level functionality to create and place objects into -complex 3D scenes, and uses the viewer architecture internally to show -the result in your chosen viewer. - -### Invoking a 3D viewer - - -A 3D viewer can be created in a script by passing the appropriate option -to `Draw() `when attaching the drawn object(s) to a pad. For a fuller -explanation of pads, attaching objects with `Draw()` etc. refer to -"Graphical Containers: Canvas and Pad". - -``` {.cpp} -root[] myShapes->Draw("ogl"); -``` - -Valid option strings are: - -- "`ogl`" : external GL viewer - -- "`x3d`": external X3D viewer - -- "`pad`": pad viewer - -If no option is passed to `Draw()` then the "`pad`" is used by default. -If you already have content in a pad, which you would like to display in -one of the external viewers you can select from the canvas View menu / -View With, and pick the viewer type. - -![Invoking external 3D viewers from canvas menus](pictures/030000D9.png) - -Note: A current limitation means that when an external viewer is created -the pad is no longer redrawn. When the external viewer is closed, -clicking in the pad will refresh. - -### The GL Viewer - - -The GL Viewer uses (or compliant libraries such as ) -to generate high quality, high-performance 3D renderings, with -sophisticated lighting, materials and rendering styles for 3D scenes. -Many users will be able to take advantage of hardware acceleration of -the underlying OpenGL commands by their computer's video card, resulting -is considerable performance gains - up to interactive manipulation of -1000's of complex shapes in real-time. - -The GL Viewer is supported on all official ROOT platforms (assuming you -have suitable libraries), and is the main 3D viewer, which -development effort is concentrated upon. As OpenGL® is a trademark we -refer to our viewer built on this technology as the ‘GL Viewer'. The -code for it can be found under `$ROOTSYS/gl`. - -![The GL 3D Viewer](pictures/020000DA.jpg) - -You can manipulate the viewer via the GUI or via the base -**`TGLViewer`** object behind the interface. These are detailed below - -see also `$ROOTSYS/tutorials/visualisation/gl/glViewerExercise.C`. - -#### Projections Modes (Cameras) - -The GL Viewer supports two basic types of camera, which affect how the -3D world is projected onto the 2D render area: - -- Perspective: Objects are drawn with characteristic ‘foreshortening' - effect, where distant objects appear smaller than near ones. This is - useful for obtaining a ‘real world' views. The degree of - foreshortening is affected by the current camera field of view - (focal length of its ‘lens') - see "Adjusting Cameras". - -- Orthographic: Distance from camera does not affect object size. - These projections are useful for measurement or checking alignments, - as the sizes and angles between objects are preserved. - -You can select the active camera from the viewer's Camera menu on the -top menu bar. There are three perspective camera choices: - -- Perspective (Floor XOZ) Default - -- Perspective (Floor YOZ) - -- Perspective (Floor XOY) - -In each case the perspective camera is constrained to keep the chosen -floor plane, defined by a pair of world axes, appearing level at all -times - i.e. there is no banking of the ‘horizon' that you experience -when a plane rolls. There are also three orthographic camera choices: - -- Orthographic (XOY) - -- Orthographic (XOZ) - -- Orthographic (ZOY) - -Orthographic projections are generally constrained to look down one of -the global axes of the world, with the other two axes lying -horizontal/vertical on the viewer window. Therefore, XOY has the X-axis -horizontal, the Y-axis vertical. You can always confirm the orientation -and constraints of the camera in the world by enabling axis drawing in -the "Guides" tab - see sections "Guides" and "Clipping" below. For -orthographic camera a ruler-depicting current scene units is also -available. - -You can also pick the current camera by obtaining a handle to the GL -Viewer object behind the interface: - -``` {.cpp} -TGLViewer * v = (TGLViewer *)gPad->GetViewer3D(); -``` - -calling the method `TGLViewer::SetCurrentCamera` with one of the -**`TGLViewer::ECameraType` types:** - -``` {.cpp} -v->SetCurrentCamera(TGLViewer::kCameraPerspXOZ); -``` - -See also `$ROOTSYS/tutorials/visualisation/gl/glViewerExercise.C`. - -#### Adjusting Cameras - -The interactions with the camera are summarized above. In each case the -interaction is listed, along with description and user actions required -to achieve it. For all cameras you can reset the original default view, -framing the entire scene, by double clicking any mouse button. - -![GL Viewer camera interactions](pictures/020000DB.jpg) - -For the Zoom interaction you can use the following modifiers -combinations to adjust the sensitivity: - -- Shiftx 10 - -- Ctrlx 0.1 - -- Shift + Ctrlx 0.01 - -The modifiers must be applied after the zoom action has started (right -mouse button is down). - -Note for orthographic cameras: - -- There is no field of view of view/focal length - dollying and - zooming producing an identical scaling action. - -- There is a fixed eye direction - so the ‘Orbit' action is disabled. - -Note for perspective cameras: - -- Dollying (moving the camera backwards/forwards) and zooming are - often confused, and may appear very similar. - -- When you dolly the camera the lens focal length does not change, - hence the distortions associated with the projections are - unaffected. However the movement can result in objects coming - ‘through the front' of the camera and disappearing. - -- When you zoom, the camera does not move - hence clipping of near - objects is unaffected. However with extremely small zooms (FOV - large/focal length short) noticeable distortions, causing straight - lines to become curved, can be seen with objects near the camera - - the ‘fisheye' lens effect. - -- Generally dollying is more ‘natural', but you may need to use both - to achieve the desired perspective and eye position - particularly - when you are working inside or very close to 3D objects. - -Configure the camera by calling the methods `SetPerspectiveCamera(`) or -`SetOrthographicCamera()` of **`TGLViewer`**: - -``` {.cpp} -TGLViewer * v = (TGLViewer *)gPad->GetViewer3D(); -v->SetOrthoCamera(TGLViewer::kCameraOrthoXOY, - left,right,top,bottom); -... -v->SetPerspectiveCamera (camera,fov,dolly,center,hRotate,vRotate); -``` - -Note - you can configure any of the six cameras in the viewer at any -time, but you will not see the result until the camera is made current. - -#### Draw Styles - -The GL Viewer supports three different rendering modes, which are -applied to all the objects in your scene, but not Clip Shapes and Guides -(See "Clipping" and "Manipulators"). These are shown below, along with -the key used to activate the style. - -![GL Viewer draw styles](pictures/020000DC.jpg) - -**Filled Polygons** **Wireframe** **Outline** Enable with ‘r' key Enable -with ‘w' key Enable with ‘t' key Solid polygons, with hidden surface -Object edges in color, with Combination of Filled Polygons removal, -color surface materials, no surface filling/hiding. and Outline styles. -Solid opacity, specular reflection etc. shapes with edges. Black -background. Black background. White background. - -Call method `TGLViewer::SetStyle` with one of -**`TGLRnrCtx::EDrawStyle `flags `kFill`, `kOutline`, `kWireFrame`:** - -``` {.cpp} -v->SetStyle(TGLRnrCtx::kFill); -``` - -#### Lighting / Style - -The GL viewer creates five diffuse lights (left, right, top, bottom, and -front) arranged around the 3D scene. These lights are carried with the -camera - that is they are always in same position relative to your eye - -the left light always shines from the left. - -Light controls are located: Viewer Controls Pane ‘Style'. - -Each light has a checkbox to enable/disable it. Set lights on/off with -**`TGLLightSet::SetLight` e.g.** - -``` {.cpp} -v->GetLightSet()->SetLight(TGLLightSet::kLightBottom, kFALSE); -``` - -#### Clipping - -The GL viewer supports interactive clipping, enabling you to remove -sections of your 3D scene and the shapes, revealing internal details. - -![GL Viewer interactive box clipping](pictures/020000DD.jpg) - -The controls for clipping can be found under: Viewer Controls Pane -‘Clipping' tab. - -Two clipping ‘shapes' are currently supported: - -- Single plane - -- Box - -Pick the type from the radio buttons - only one (or none) may be active -at one time. - -The clip object can be adjusted by: - -- Adjusting the values in the properties panel GUI - -- Directly manipulating the clip object in the viewer - -To show and/or directly manipulate the object check the ‘Show / Edit in -Viewer' checkbox. The clip object is drawn in semi-transparent light -brown. The current manipulator is attached to it, allowing you direct -control over its position, scale and rotation. See "Manipulators" -section below for details on using viewer manipulators. - -The clip plane is described by the standard plane equation: -**`ax+by+cz+d=0`**, where the factors **`a`**, **`b`**, **`c`**, -**`d`** are entered into the edit boxes, and applied using the ‘Apply' -button. - -The clip box is described by its center position, entered in the ‘Center -X', ‘Center Y' and ‘Center Z' edit boxes, and its lengths (extents) -entered in the ‘Length X', ‘Length Y' and ‘Length Z' edit boxes. - -This clipping is achieved using OpenGL clip plane support; as such, -there are certain limitations: - -- Solid shapes are not capped - they appear hollow. - -- Only shapes, which can be described with combination of planes, can - be rendered in this fashion - e.g. a clipping tube is not possible. - -- Each additional clipping plane requires an additional render pass - - so the more active planes the more time the render will take. - -Set the current clip object with **`TGLClipSet::SetClipType`** - -``` {.cpp} -v->GetClipSet()->SetClipType(TGLClipSet::kClipPlane); -``` - -Configure the clip object with **`TGLClipSet::SetClipState`** - -``` {.cpp} -Double_t planeEq[4] = {0.5,1.0,-1.0, 2.0}; -v->GetClipSet()->SetClipState(TGLClipSet::kClipPlane, planeEq); -``` - -As with cameras, any clip can be configured at any time, but you must -set the clip current to see the effect. - -#### Manipulators - -*Manipulators* are GUI ‘widgets' or controls attached to a 3D object in -the viewer, allowing a direct manipulation of the object's geometry. -There are three manipulators for the three basic geometries -transformations. In each case, the *manipulator* consists of three -components, one for each local axis of the object, shown in standard -colors: red (X), green (Y) and blue (Z). - -![GL Viewer object manipulators](pictures/030000DE.png) - -Activate the *manipulator* by moving the mouse over one of these -components (which turns yellow to indicate active state). Click with -left mouse and drag this active component to perform the manipulation. -Toggle between the *manipulator* types using the ‘x', ‘c', ‘v' keys -while the mouse cursor is above the manipulator. Note: Manipulators -cannot be controlled via the API at present. - -#### Guides - -Guides are visual aids drawn into the viewer world. Controls for these -are under the "Guides" tab: - -Viewer Controls Pane Guides Tab - -Axes show the world (global) frame *coordinate*directions: X (red), Y -(green) and Z (blue). The negative portion of the *axis* line is shown -in dark color, the positive in bright. The *axis* name and minimum / -maximum values are labeled in the same color. There are three options -for *axes* drawing - selected by radio buttons: - -- None - not drawn (default). - -- Edge - draw axes on the (minimum) edge of the scene extents box. - -- Origin - drawn axes through the origin. - -For *edge axes*, the zero value for each axis is marked on the axis line -with a colored sphere. For *origin axes,* a single white sphere is shown -at the origin. - -*Edge axes* are depth clipped - i.e. are obscured by 3D objects in front -of them. *Origin axes* (which generally pass through the middle of the -3D scene) are not depth clipped - so always visible. - -A single orange sphere of fixed view port (window) size can be shown at -any arbitrary position. Enable / disable the drawing with ‘*Show'* -checkbox. Enter X/Y/Z position in the edit boxes to set position. -Initial position is at the center of the scene. - -Set the guides using `TGLViewer::SetGuideState` e.g. to enable edge -axes, and enable a reference marker at world position 50, 60, 100: - -``` {.cpp} -Double_t refPos[3] = {50.0,60.0,100.0}; -v->SetGuideState(TGLUtil::kAxesEdge, kTRUE, refPos); -``` - -#### Selecting Scene Shapes - -You can select a single shape from your scene by pressing ‘Shift' key, -pointing and left clicking anywhere on the shape in the viewer. -Selection is currently shown by drawing the shape-bounding box (not -depth clipped) in white (polygon or wire frame render styles) or red -(outline render style). Manipulators supported by the shape are drawn in -red, green and blue while the non-supported ones are drawn in grey. To -deselect a shape, either select another, or shift/click anywhere on the -background (empty space) in the viewer. You cannot select Manipulators -or Guides (Axes / Reference Marker). - -#### Editing Shapes - -When a shape is selected, the viewer's control pane shows the user -interface that allows you to review and adjust the color and geometry -properties of the shape. - -Note: At present modifications to the shapes are local to the viewer - -they are not propagated back to external objects/client that published -to the viewer. The changes are preserved only until the viewer is -closed. In some cases, this will never be feasible as there is not a -one-to-one correspondence between a shape in the viewer and a single -external object in which the modification could be stored. - -#### Colors / Style - -Viewer Controls Pane ‘Style' tab. - -A full description of OpenGL materials, colors and lighting is beyond -the scope of this document. You should refer to the OpenGL programming -manual (Red Book) for a full discussion. In most cases adjustment of the -Diffuse color material + Opacity/Shine properties is sufficient to -achieve desired results. - -A shape has four-color materials (components): - -- Diffuse - -- Ambient - -- Specular - -- Emissive - -For each of these you can select the component via the radio buttons. -Each component can have the red, green and blue values for the component -adjusted via the sliders. You can apply this adjustment to the shape -itself, or to all shapes sharing a common ‘family'. Shapes of the same -family have external objects with the same **`TObject`** name string. -You can also adjust the ‘Opacity' and ‘Shine' for the shapes materials -via the sliders. - -#### Geometry - -Viewer Controls Pane ‘Geometry' tab. - -Review and modify the shapes X/Y/Z center and scaling factors via the -edit boxes. Selection and editing of shapes is not available via the API -at present. - -#### Outputting Viewer Contents - -The current viewer rendering can be output to an external `EPS` or -`PDF`, using the options under the ‘File' menu on the top menu bar. The -file is named ‘`viewer.eps`' or ‘`viewer.pdf`' and written to the -current ROOT directory. - -### The X3D Viewer - - -The X3D viewer is a fairly simple and limited viewer, capable of showing -basic lines and polygons. It lacks the quality, performance and more -advanced features of the GL Viewer, and additionally is not supported on -Windows. It is not actively developed and you are encouraged to use the -GL Viewer out of preference. The below table presents the main -interactions - these are repeated in the Help dialog of the viewer. - -Action KeyActionKey - -Wireframe Mode wRotate about xx a - -Hidden Line Mode eRotate about yy b - -Hidden Surface Mode rRotate about zz c - -Move object down uAuto-rotate about x1 2 3 - -Move object up iAuto-rotate about y4 5 6 - -Move object left lAuto-rotate about z7 8 9 - -Move object right hToggle controls styleo - -Move object forward jToggle stereo displays - -Move object backward kToggle blue stereo viewd - -Adjust focus (stereo mode) [ ] { }Toggle double bufferf - -Rotate object Left mouse button down + move. - -### Common 3D Viewer Architecture - - -The 3D Viewer Architecture provides a common mechanism for viewer -clients to publish 3D objects to it. It enables: - -- Decoupling of producers (geometry packages etc) who model collection - of 3D objects from consumers (viewers) which display them. - -- Producer code free of explicit drawing commands & viewer specific - branching. - -- Support differing viewers and clients capabilities, e.g. - -- Mix of native (in viewer) shapes and generic client side - tessellation. - -- Local/global frame object description - -- Bounding boxes - -- Placing copies sharing common geometry (logical/physical shapes). - -The architecture consists of: - -- **`TVirtualViewer3D`** interface: An abstract handle to the viewer, - allowing client to add objects, test preferences etc. - -- **`TBuffer3D`** class hierarchy: Used to describe 3D objects - ("shapes") - filled /added by negotiation with viewer via - **`TVirtualViewer3D`**. - -A typical interaction between viewer and client using these, taken from -**`TGeoPainter`** is: - -``` {.cpp} -TVirtualViewer3D * viewer = gPad->GetViewer3D(); -// Does viewer prefer local frame positions? -Bool_t localFrame = viewer->PreferLocalFrame(); -// Perform first fetch of buffer from the shape and try adding it to the viewer -const TBuffer3D &buffer = shape.GetBuffer3D(TBuffer3D::kCore | -TBuffer3D::kBoundingBox | -TBuffer3D::kShapeSpecific, -localFrame); -Int_t reqSections = viewer->AddObject(buffer, &addDaughters); - -// If the viewer requires additional sections fetch from the shape -// (if possible) and add again -if (reqSections != TBuffer3D::kNone) -shape.GetBuffer3D(reqSections, localFrame); -``` - -Together these allow clients to publish objects to any one of the 3D -viewers free of viewer specific drawing code. They allow our simple x3d -viewer, and considerably more sophisticated OpenGL one to both work with -both geometry libraries (`g3d` and `geom`) efficiently. - -In addition to external viewers, created in separate windows, this -architecture is also used by internal **`TPad`** drawing when it -requires 3D projections. Publishing to a viewer consists of the -following steps: - -1- Create / obtain viewer handle. - -2- Begin scene on viewer. - -3- Fill mandatory parts of TBuffer3D describing object. - -4- Add to viewer. - -5- Fill optional parts of TBuffer3D as requested by viewer. - -[ .... repeat 3/4/5 as required for other/child objects] - -6- End scene on viewer. - -You should attach the top-level node of your external geometry (or the -manager) to a **`TPad`** object using **`TObject::Draw()`, and perform -the publishing to the viewer in your object's `TObject::Paint()` -overloaded method. See "Scene Rebuilds", and example scripts, for more -details.** - -#### Creating / Obtaining Viewer Handle - -External viewers are bound to a **`TPad`** object (this may be removed -as a requirement in the future). You can create or obtain the current -viewer handle via the method: - -``` {.cpp} -TVirtualViewer3D * v = gPad->GetViewer3D("type"); -``` - -Here the "type" string defines the viewer type - currently one of: - -- "`ogl`" : External GL viewer - -- "`x3d`": External X3D viewer - -- "`pad`": Pad viewer - -If no type is passed (null string), and there is no current viewer, then -the type is defaulted to "`pad`". If no type is passed and there is a -current viewer, then this is returned - hence once a viewer is created -it can be obtained elsewhere by: - -``` {.cpp} -TVirtualViewer3D * v = gPad->GetViewer3D(); -``` - -#### Opening / Closing Scenes - -Objects must be added to viewer between `BeginScene()` and `EndScene()` -calls e.g. - -``` {.cpp} -viewer->BeginScene(); -// Add objects -viewer ->EndScene(); -``` - -These calls enable the viewer to suspend redraws, and perform internal -caching/setup. If the object you attach to the pad derives from -**`TAtt3D`**, then the pad will take responsibility for calling -`BeginScene()` and `EndScene()` for you. You can always test if the -scene is already open for object addition with: - -``` {.cpp} -viewer->BuildingScene(); -``` - -![Overview of 3D viewer architecture](pictures/030000DF.png) - -Note: the x3d viewer does not support rebuilding of scenes - objects -added after the first Open/Close Scene pair will be ignored. - -#### Describing Objects - Filling TBuffer3D - -The viewers behind the **`TVirtualViewer3D`** interface differ greatly -in their capabilities e.g. - -- Some support native shape (e.g. spheres/tubes in OpenGL) and can - draw these based on an abstract description. Others always require a - tessellation description based on **`TBuffer3D`**'s `kRaw` / - `kRawSizes` points/lines/segments sections. - -- Some need the 3D object positions in the master (world) frame, - others can cope with local frames and a translation matrix to place - the object. - -- Some require bounding boxes for objects - others do not. - -Similarly some viewer clients are only capable of providing positions in -master frame, cannot provide bounding boxes etc. Additionally we do not -want to incur the cost of expensive tessellation operations if the -viewer does not require them. To cope with these variations the -**`TBuffer3D`** objects are filled by negotiation with the viewer. - -![TBuffer3D class hierarchy](pictures/030000E0.png) - -**`TBuffer3D`** classes are conceptually divided into enumerated -sections: `kCore`, `kBoundingBox`, `kRaw` - see the class diagram and -the file `TBuffer3D.h` for more details. The **`TBuffer3D`** methods -`SectionsValid()`, `SetSectionsValid()`, `ClearSectionsValid()` are used -to test, set, clear these section validity flags e.g. - -``` {.cpp} -buffer.SetSectionsValid(TBuffer3D::kShapeSpecific); -... -if (buffer.SectionsValid(TBuffer3D:: kShapeSpecific)) { - ... -} -``` - -The sections found in the base **`TBuffer3D`** -(`kCore/kBoundingBox/kRawSizes/kRaw`) are sufficient to describe any -tessellated shape in a generic fashion. An additional `kShapeSpecific` -section is added in **`TBuffer3D`** derived classes, allowing a more -abstract shape description ("a sphere of inner radius x, outer radius -y"). This enables a viewer, which knows how to draw (tessellate) the -shape itself to do so, while providing a generic fallback suitable for -all viewers. The rules for client negotiation with the viewer are: - -- If suitable specialized **`TBuffer3D`** class exists, use it, - otherwise use **`TBuffer3D`**. - -- Complete the mandatory `kCore` section. - -- Complete the `kShapeSpecific` section if applicable. - -- Complete the `kBoundingBox` if you can. - -- Pass this buffer to the viewer using one of the - `TBuffer3D::AddObject()` methods. - -If the viewer requires more sections to be completed (`kRaw/kRawSizes`) -`TBuffer3D::AddObject()` will return flags indicating which ones, -otherwise it returns `kNone`. If requested, you must fill the buffer, -mark these sections valid, and call `TBuffer3D::AddObject` again, to -complete adding the object. For example, in out **`TGeo`** geometry -package, in `TGeoPainter::PaintShape`, we perform the negotiation with -viewer: - -``` {.cpp} -TVirtualViewer3D * viewer = gPad->GetViewer3D(); -if (shape.IsA() != TGeoCompositeShape::Class()) { - // Does viewer prefer local frame positions? - Bool_t localFrame = viewer->PreferLocalFrame(); - // Perform first fetch of buffer from the shape and adding - // it to the viewer - const TBuffer3D &buffer = shape.GetBuffer3D(TBuffer3D::kCore | - TBuffer3D::kBoundingBox | - TBuffer3D::kShapeSpecific, localFrame); - Int_t reqSections = viewer->AddObject(buffer, &addDaughters); - // If the viewer requires additional sections fetch from the - // shape (if possible) and add again - if (reqSections != TBuffer3D::kNone) { - shape.GetBuffer3D(reqSections, localFrame); - viewer->AddObject(buffer, &addDaughters); - } -} -``` - -The buffer is supplied/filled by the appropriate `TShape::GetBuffer3D()` -and **`TShape::FillBuffer3D` overloads e.g. for a sphere in -`TGeoSphere`**. - -``` {.cpp} -const TBuffer3D &TGeoSphere::GetBuffer3D(Int_t reqSections, -Bool_t localFrame) const { - // Fills a static 3D buffer and returns a reference. - static TBuffer3DSphere buffer; - // Filling of kBoundingBox is defered to TGeoBBox, and - // kCore on up to TGeoShape - TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame); - // Complete kShapeSpecific section for sphere - if (reqSections & TBuffer3D::kShapeSpecific) { - buffer.fRadiusInner = fRmin; - buffer.fRadiusOuter = fRmax; - ... - buffer.SetSectionsValid(TBuffer3D::kShapeSpecific); - } - // Complete kRawSizes section - if (reqSections & TBuffer3D::kRawSizes) { - ... - buffer.SetSectionsValid(TBuffer3D::kRawSizes); - } -} - // Complete kRaw tesselation section - if ((reqSections & TBuffer3D::kRaw) && - buffer.SectionsValid(TBuffer3D::kRawSizes)) { - SetPoints(buffer.fPnts); - // Transform points to master frame if viewer requires it - // The fLocalFrame flag and translation matrix will have - // already been set in TGeoShape::FillBuffer3D() as required - if (!buffer.fLocalFrame) - TransformPoints(buffer.fPnts, buffer.NbPnts()); - SetSegsAndPols(buffer); - buffer.SetSectionsValid(TBuffer3D::kRaw); - } - return buffer; -} -``` - -Note: - -- we use a static **`TBuffer3D`** derived object for efficiency - once - the object is added the buffer can be reused. - -- `kRawSize` (the calculation of tessellation sizing required in - buffer) and `kRaw` (the actual filling of tessellation) is split, as - the X3D viewer requires two publication passes - one to establish - the full tessellation capacity for all shapes, and another to - actually add them. Splitting avoids having to do the expensive - tessellation on the first pass. - -#### Shape Specific TBuffer3D Derived Classes - -Currently we provide the following shape specific classes, which the GL -Viewer can take advantage of (see `TBuffer3D.h` and `TBuffer3DTypes.h`) - -- **`TBuffer3DSphere`** - solid, hollow and cut spheres (GL Viewer - only supports solid spheres at present - cut / hollow ones will be - requested as tessellated objects by client.) - -- **`TBuffer3DTube`** - basic tube with inner/outer radius and length. - -- **`TBuffer3DTubeSeg`** - angle tube segment. - -- **`TBuffer3DCutTube`** - angle tube segment with plane cut ends. - -See the above example from `TGeoSphere::GetBuffer3D` and also equivalent -functions in **`TGeoTube`**, **`TGeoTubeSeg`** and **`TGeoCtub`**. -Anyone is free to add new **`TBuffer3D`** classes, but it should be -clear that one or more viewers will require updating to be able to take -advantage of them. Hence we only provide classes which existing viewers -can benefit from. The number of native shapes in GL Viewer will be -expanded in the future. - -#### Master / Local Reference Frames - -The Core section of **`TBuffer3D`** contains two members relating to -reference frames: - -- `fLocalFrame`: indicates if any positions in the buffer (bounding - box and tessellation vertexes) are in local or master (world frame). - -- `fLocalMaster`: is a standard 4x4 translation matrix (OpenGL column - major ordering) for placing the object into the 3D master frame. - -If `fLocalFrame` is false, `fLocalMaster` should contain an identity -matrix. This is set by default, and can be reset using the -**`TBuffer3D::SetLocalMasterIdentity()` method.** - -#### Bounding Boxes - -You are not obliged to complete the `kBoundingBox` section, as any -viewer requiring one internally (GL Viewer) will build it if you do not -provide. However to do this the viewer will force you to provide the -(expensive) raw tessellation, and the resulting box will be axis aligned -with the overall scene, which is non-ideal for rotated shapes. As we -need to support orientated (rotated) bounding boxes, **`TBuffer3D`** -requires the 6 vertices of the box. We also provide a convenience -function, `TBuffer::SetAABoundingBox()`, for simpler case of setting an -axis aligned bounding box. The bounding box should be filled in same -frame (local / master) as the rest of the **`TBuffer3D`**, and -in accordance with `fLocalFrame` flag. - -A typical example from TGeoBBox::FillBuffer3D: - -``` {.cpp} - if (reqSections & TBuffer3D::kBoundingBox) { - Double_t halfLengths[3] = { fDX, fDY, fDZ }; - buffer.SetAABoundingBox(fOrigin, halfLengths); - if (!buffer.fLocalFrame) { - TransformPoints(buffer.fBBVertex[0], 8); - } - buffer.SetSectionsValid(TBuffer3D::kBoundingBox); - } -``` - -#### Logical and Physical Objects - -Some viewers can support two types of object placement: - -- Add object as a single independent entity in the world reference - frame - e.g. a sphere, radius `r`, at `x`, `y`, `z`. - -- Repeated placement (copying) in world frame of this locally unique - piece of geometry (described in local reference frame) e.g. define a - sphere `S` (radius `r`), place copy at `x1`, `y1`, `z1`, another - copy at `x2`, `y2`, `z2` etc. - -The second case is very typical in geometry packages, e.g. ROOT's -**`TGeo`** package, GEANT4 etc, where we have very large number repeated -placements of relatively few unique "shapes". - -Some viewers (GL Viewer only at present) are able to take advantage of -this by identifying unique logical shapes from the `fID` logical ID -member of **`TBuffer3D`**. If repeated addition of the same `fID` is -found, the shape is cached already - and the costly tessellation does -not need to be sent again. The viewer can also perform internal GL -specific caching (display lists) with considerable performance gains in -these cases. For this to work correctly the logical object in must be -described in **`TBuffer3D`** in the local reference frame, complete with -the local`/`master translation. In some cases you will not have a real -object you can reasonably set **`TBuffer3D::fID` to, or the object is -recycled or temporary. To suppress internal caching in the GL Viewer in -these cases, set `TBuffer3D::fID` to 0 (null).** - -The viewer indicates it can support local frame objects through the -**`TVirtualViewer3D`** interface method: `PreferLocalFrame()`. If this -returns `kTRUE` you can make repeated calls to `AddObject()`, with -**`TBuffer3D`** containing the same `fID`, and different `fLocalMaster` -placements. - -For viewers supporting logical/physical objects, the TBuffer3D content -refers to the properties of the logical object, with the exception of: - -- `fLocalMaster` transform - -- `fColor ` - -- `fTransparency` - -attributes, which can be varied for **each** physical object. - -As **a minimum requirement** all clients must be capable of filling the -raw tessellation of the object buffer, in the master reference frame. -Conversely viewers must always be capable of displaying the object -described by this buffer. If either does not meet this requirement the -object may not be displayed. - -#### Scene Rebuilds - -`TBuffer3D::AddObject` is not an explicit command to the viewer - it may -for various reasons decide to ignore it: - -- It already has the object internally cached. - -- The object falls outside some 'interest' limits of the viewer - camera. - -- The object is too small to be worth drawing. - -In all these cases `TBuffer3D::AddObject()` returns kNone, as it does -for successful addition, indicating it does not require further -information about this object. Hence you should not try to make any -assumptions about what the viewer did with the object. The viewer may -decide to force the client to rebuild (republish) the scene, obtaining a -different collection of objects, if the internal viewer state changes -.e.g. significant camera move. It does this presently by forcing a -repaint on the attached **`TPad`** object - hence you should attach you -master geometry object to the pad (via `TObject::Draw()`), and perform -the publishing to the viewer in response to **`TObject::Paint()`**. - -#### Physical IDs - -TVirtualViewer3D provides for two methods of object addition: - -``` {.cpp} -virtual Int_t AddObject(const TBuffer3D &buffer, - Bool_t * addChildren = 0) -virtual Int_t AddObject(UInt_t physicalID, - const TBuffer3D & buffer, - Bool_t *addChildren = 0) -``` - -If you use the first (simple) case a viewer using logical/physical pairs -will generate sequential IDs for each physical object internally. Scene -rebuilds will require destruction and recreation of all physical -objects. For the second you can specify an identifier from the client -side, which must be unique and stable - i.e. the IDs of a published -object is consistent, regardless of changes in termination of contained -child geometry branches. In this case the viewer can safely cache the -physical objects across scene rebuilds, discarding those no longer of -interest. - -#### Child Objects - -In many geometries there is a rigid containment hierarchy, and so if the -viewer is not interested in a certain object due to limits/size then it -will also not be interest in any of the contained branch of siblings. -Both `TBuffer3D::AddObject()` methods have an `addChildren` return -parameter. The viewer will complete this (if passed) indicating if -children of the object just sent are worth sending. - -#### Recycling TBuffer3D - -Once add `TBuffer3D::AddObject()` has been called, the contents are -copied to the viewer's internal data structures. You are free to destroy -this **`TBuffer3D`**, or recycle it for the next object if suitable. - -#### Examples - -For an example of a simple geometry, working in master reference frame -examine the code under `$ROOTSYS/g3d`. For a more complex example, which -works in both master and local frames, and uses logical`/`physical -division of shape geometry and placement, examine the code under -`$ROOTSYS/geom` - in particular **`TGeoShape`** hierarchy, and the -painter object **`TGeoPainter`** (under geopainter) where the -negotiation with the viewer is performed. diff --git a/documentation/users-guide/Graphs.md b/documentation/users-guide/Graphs.md deleted file mode 100644 index 3f7916bb97329..0000000000000 --- a/documentation/users-guide/Graphs.md +++ /dev/null @@ -1,762 +0,0 @@ -# Graphs - - -A graph is a graphics object made of two arrays X and Y, holding the -x,y coordinates of `n` points. There are several graph classes; they -are **`TGraph`**, **`TGraphErrors`**, **`TGraphAsymmErrors`**, and -**`TMultiGraph`**. - -## TGraph - - -The **`TGraph`** class supports the general case with non-equidistant -points, and the special case with equidistant points. Graphs are -created with the **`TGraph`** constructor. First, we define the arrays -of coordinates and then create the graph. The coordinates can be -arrays of doubles or floats. - -``` {.cpp} - Int_t n = 20; - Double_t x[n], y[n]; - for (Int_t i=0; iDraw("AC*"); -} -``` - -#### Bar Graphs (AB) - -![A graph drawn with axis and bar (option AB)](pictures/0300004C.png) - -``` {.cpp} -root[] TGraph *gr1 = new TGraph(n,x,y); -root[] gr1->SetFillColor(40); -root[] gr1->Draw("AB"); -``` - -This code will only work if n, x, and y is defined. The previous -example defines these. You need to set the fill color, because by -default the fill color is white and will not be visible on a white -canvas. You also need to give it an axis, or the bar chart will not be -displayed properly. - -#### Filled Graphs (AF) - -![A graph drawn with axis and fill (option AF)](pictures/0300004D.png) - -``` {.cpp} -root[] TGraph *gr3 = new TGraph(n,x,y); -root[] gr3->SetFillColor(45); -root[] gr3->Draw("AF") -``` - -This code will only work if `n`, `x`, `y `are defined. The first -example defines them. You need to set the fill color, because by -default the fill color is white and will not be visible on a white -canvas. You also need to give it an axis, or the filled polygon will -not be displayed properly. - -#### Marker Options - -![Graph markers created in different ways](pictures/0300004E.png) - -``` {.cpp} -{ - Int_t n = 20; - Double_t x[n], y[n]; - - // build the arrays with the coordinate of points - for (Int_t i=0; iSetMarkerStyle(21); - c1->cd(4); - gr3->Draw("APL"); - - // get the points in the graph and put them into an array - Double_t *nx = gr3->GetX(); - Double_t *ny = gr3->GetY(); - - // create markers of different colors - for (Int_t j=2; jSetMarkerSize(2); - m->SetMarkerColor(31+j); - m->Draw(); - } -} -``` - -## Superimposing Two Graphs - - -To super impose two graphs you need to draw the axis only once, and -leave out the "A" in the draw options for the second graph. Next is an -example: - -![Superimposing two graphs](pictures/0300004F.png) - -``` {.cpp} -{ - Int_t n = 20; - Double_t x[n], y[n], x1[n], y1[n]; - - // create a blue graph with a cos function - gr1->SetLineColor(4); - gr1->Draw("AC*"); - - // superimpose the second graph by leaving out the axis option "A" - gr2->SetLineWidth(3); - gr2->SetMarkerStyle(21); - gr2->SetLineColor(2); - gr2->Draw("CP"); -} -``` - -## Graphs with Error Bars - - -A **`TGraphErrors`** is a **`TGraph`** with error bars. The various -draw format options of `TGraphErrors::Paint()` are derived from -**`TGraph`**. - -``` {.cpp} -void TGraphErrors::Paint(Option_t *option) -``` - -![Graphs with different draw options of error bars](pictures/03000050.png) - -In addition, it can be drawn with the "`Z`" option to leave off the -small lines at the end of the error bars. If option contains "`>`", an -arrow is drawn at the end of the error bars. If option contains -"`|>`", a full arrow is drawn at the end of the error bars. The size -of the arrow is set to 2/3 of the marker size. - -The option "`[]`" is interesting to superimpose systematic errors on -top of the graph with the statistical errors. When it is specified, -only the end vertical/horizontal lines of the error bars are drawn. - -To control the size of the lines at the end of the error bars (when -option 1 is chosen) use `SetEndErrorSize(np)`. By default `np=1`; `np` -represents the number of pixels. - -``` {.cpp} -gStyle->SetEndErrorSize(np); -``` - -The four parameters of **`TGraphErrors`** are: `X, Y` (as in -**`TGraph`**), `X`-errors, and `Y`-errors - the size of the errors -in the `x` and `y` direction. Next example is -`$ROOTSYS/tutorials/visualisation/graphs/gr002_errors.C.` - -``` {.cpp} -{ - c1 = new TCanvas("c1","A Simple Graph with error bars",200,10,700,500); - c1->SetGrid(); - - // create the coordinate arrays - Int_t n = 10; - Float_t x[n] = {-.22,.05,.25,.35,.5,.61,.7,.85,.89,.95}; - Float_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; - - // create the error arrays - Float_t ex[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05}; - Float_t ey[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8}; - - // create the TGraphErrors and draw it - gr = new TGraphErrors(n,x,y,ex,ey); - gr->SetTitle("TGraphErrors Example"); - gr->SetMarkerColor(4); - gr->SetMarkerStyle(21); - gr->Draw("ALP"); - c1->Update(); -} -``` - -## Graphs with Asymmetric Error Bars - -![A graph with asymmetric error bars](pictures/03000052.png) - -A **`TGraphAsymmErrors`** is a **`TGraph`** with asymmetric error -bars. It inherits the various draw format options from **`TGraph`**. -Its method `Paint(Option_t *option)` paints the -**`TGraphAsymmErrors`** with the current attributes. You can set the -following additional options for drawing: - -- "`z`" or "`Z`"the horizontal and vertical small lines are not - drawn at the end of error bars - -- "`>`"an arrow is drawn at the end of the error bars - -- "`|>`"a full arrow is drawn at the end of the error bar; its size - is $\frac{2}{3}$ of the marker size - -- "`[]`"only the end vertical/horizontal lines of the error bars are - drawn; this option is interesting to superimpose systematic errors - on top of a graph with statistical errors. - -The constructor has six arrays as parameters: X and Y as **TGraph** -and low X-errors and high X-errors, low Y-errors and high Y-errors. -The low value is the length of the error bar to the left and down, -the high value is the length of the error bar to the right and up. - -``` {.cpp} -{ - c1 = new TCanvas("c1","A Simple Graph with error bars", - 200,10,700,500); - c1->SetGrid(); - - // create the arrays for the points - Int_t n = 10; - Double_t x[n] = {-.22,.05,.25,.35,.5, .61,.7,.85,.89,.95}; - Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; - - // create the arrays with high and low errors - Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05}; - Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8}; - Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03}; - Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6}; - - // create TGraphAsymmErrors with the arrays - gr = new TGraphAsymmErrors(n,x,y,exl,exh,eyl,eyh); - gr->SetTitle("TGraphAsymmErrors Example"); - gr->SetMarkerColor(4); - gr->SetMarkerStyle(21); - gr->Draw("ALP"); -} -``` - -## Graphs with Asymmetric Bent Errors - -![A graph with asymmetric bent error bars](pictures/03000053.png) - -A **`TGraphBentErrors`** is a **`TGraph`** with bent, asymmetric error -bars. The various format options to draw a **`TGraphBentErrors`** are -explained in **`TGraphBentErrors::Paint` method. The -`TGraphBentErrors`** is drawn by default with error bars and small -horizontal and vertical lines at the end of the error bars. If option -"`z`" or "`Z`" is specified, these small lines are not drawn. If the -option "`X`" is specified, the errors are not drawn -(the `TGraph::Paint` method equivalent). - -- if option contains "`>`", an arrow is drawn at the end of the - error bars - -- if option contains "`|>`", a full arrow is drawn at the end of the - error bars - -- the size of the arrow is set to 2/3 of the marker size - -- if option "`[]`" is specified, only the end vertical/horizontal - lines of the error bars are drawn. This option is interesting to - superimpose systematic errors on top of a graph with statistical - errors. - - -This figure has been generated by the following macro: - -``` {.cpp} -{ - Int_t n = 10; - Double_t x[n] = {-0.22,0.05,0.25,0.35,0.5,0.61,0.7,0.85,0.89,0.95}; - Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; - Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05}; - Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8}; - Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03}; - Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6}; - Double_t exld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0}; - Double_t eyld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0}; - Double_t exhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0}; - Double_t eyhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.05,.0}; - gr = new TGraphBentErrors(n,x,y, - exl,exh,eyl,eyh,exld,exhd,eyld,eyhd); - gr->SetTitle("TGraphBentErrors Example"); - gr->SetMarkerColor(4); - gr->SetMarkerStyle(21); - gr->Draw("ALP"); -} -``` - -## TGraphPolar - - -The **`TGraphPolar`** class creates a polar graph (including error -bars). A **`TGraphPolar`** is a **`TGraphErrors`** represented in -polar coordinates. It uses the class **`TGraphPolargram`** to draw the -polar axis. - -``` {.cpp} -{ - TCanvas *CPol = new TCanvas("CPol","TGraphPolar Examples",700,700); - Double_t rmin=0; - Double_t rmax=TMath::Pi()*2; - Double_t r[1000]; - Double_t theta[1000]; - TF1 * fp1 = new TF1("fplot","cos(x)",rmin,rmax); - for (Int_t ipt = 0; ipt < 1000; ipt++) { - r[ipt] = ipt*(rmax-rmin)/1000+rmin; - theta[ipt] = fp1->Eval(r[ipt]); - } - TGraphPolar * grP1 = new TGraphPolar(1000,r,theta); - grP1->SetLineColor(2); - grP1->Draw("AOL"); -} -``` - -The TGraphPolar drawing options are: - -"O" Polar labels are paint orthogonally to the polargram radius. - -"P" Polymarker are paint at each point position. - -"E" Paint error bars. - -"F" Paint fill area (closed polygon). - -"A"Force axis redrawing even if a polagram already exists. - - -![A polar graph](pictures/03000054.png) - - -## TGraph Exclusion Zone - - -When a graph is painted with the option "`C`" or "`L`", it is possible -to draw a filled area on one side of the line. This is useful to show -exclusion zones. This drawing mode is activated when the absolute -value of the graph line width (set thanks to `SetLineWidth`) is -greater than 99. In that case the line width number is interpreted as -`100*ff+ll = ffll`. The two-digit numbers "`ll`" represent the normal -line width whereas "`ff`" is the filled area width. The sign of -"`ffll`" allows flipping the filled area from one side of the line to -the other. The current fill area attributes are used to draw the -hatched zone. - -![Graphs with exclusion zones](pictures/03000055.png) - -``` {.cpp} -{ - c1 = new TCanvas("c1","Exclusion graphs examples",200,10,700,500); - c1->SetGrid(); - - // create the multigraph - TMultiGraph *mg = new TMultiGraph(); - mg->SetTitle("Exclusion graphs"); - - // create the graphs points - const Int_t n = 35; - Double_t x1[n], x2[n], x3[n], y1[n], y2[n], y3[n]; - for (Int_t i=0;iSetLineColor(2); - gr1->SetLineWidth(1504); - gr1->SetFillStyle(3005); - - // create the 2nd TGraph - gr2 = new TGraph(n,x2,y2); - gr2->SetLineColor(4); - gr2->SetLineWidth(-2002); - gr2->SetFillStyle(3004); - gr2->SetFillColor(9); - - // create the 3rd TGraph - gr3 = new TGraph(n,x3,y3); - gr3->SetLineColor(5); - gr3->SetLineWidth(-802); - gr3->SetFillStyle(3002); - gr3->SetFillColor(2); - - // put the graphs in the multigraph - mg->Add(gr1); - mg->Add(gr2); - mg->Add(gr3); - - // draw the multigraph - mg->Draw("AC"); -} -``` - -## TGraphQQ - - -A **`TGraphQQ`** allows drawing quantile-quantile plots. Such plots -can be drawn for two datasets, or for one dataset and a theoretical -distribution function. - -### Two Datasets - -![Examples of qq-plots of 2 datasets](pictures/03000056.png) - -Quantile-quantile plots are used to determine whether two samples come -from the same distribution. A qq-plot draws the quantiles of one -dataset against the quantile of the other. The quantiles of the -dataset with fewer entries are on Y-axis, with more entries - on -X-axis. A straight line, going through 0.25 and 0.75 quantiles is also -plotted for reference. It represents a robust linear fit, not -sensitive to the extremes of the datasets. If the datasets come from -the same distribution, points of the plot should fall approximately on -the 45 degrees line. If they have the same distribution function, but -different parameters of location or scale, they should still fall on -the straight line, but not the 45 degrees one. - -The greater their departure from the straight line, the more evidence -there is that the datasets come from different distributions. The -advantage of qq-plot is that it not only shows that the underlying -distributions are different, but, unlike the analytical methods, it -also gives information on the nature of this difference: heavier -tails, different location/scale, different shape, etc. - -### One Dataset - -![Examples of qq-plots of 1 dataset](pictures/03000057.png) - -Quantile-quantile plots are used to determine if the dataset comes -from the specified theoretical distribution, such as normal. A qq-plot -draws quantiles of the dataset against quantiles of the specified -theoretical distribution. Note, that density, not CDF should be -specified a straight line, going through 0.25 and 0.75 quantiles could -also be plotted for reference. It represents a robust linear fit, not -sensitive to the extremes of the dataset. As in the two datasets case, -departures from straight line indicate departures from the specified -distribution. Next picture shows an example of a qq-plot of a dataset -from N(3, 2) distribution and TMath::Gaus(0, 1) theoretical function. -Fitting parameters are estimates of the distribution mean and sigma. - - -## TMultiGraph - -![A multigraph example](pictures/03000058.png) - -A **`TMultiGraph`** is a collection of **`TGraph`** (or derived) -objects. Use `TMultiGraph::Add `to add a new graph to the list. The -**`TMultiGraph`** owns the objects in the list. The drawing and -fitting options are the same as for **`TGraph`**. - -``` {.cpp} -{ - // create the points - Int_t n = 10; - Double_t x[n] = {-.22,.05,.25,.35,.5,.61,.7,.85,.89,.95}; - Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; - Double_t x2[n] = {-.12,.15,.35,.45,.6,.71,.8,.95,.99,1.05}; - Double_t y2[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; - - // create the width of errors in x and y direction - Double_t ex[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05}; - Double_t ey[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8}; - - // create two graphs - TGraph *gr1 = new TGraph(n,x2,y2); - TGraphErrors *gr2 = new TGraphErrors(n,x,y,ex,ey); - - // create a multigraph and draw it - TMultiGraph *mg = new TMultiGraph(); - mg->Add(gr1); - mg->Add(gr2); - mg->Draw("ALP"); -} -``` - -## TGraph2D - -![Delaunay triangles and Voronoï diagram](pictures/03000059.png) - -This class is a set of `N` points `x[i]`, `y[i]`, `z[i]` in a -non-uniform grid. Several visualization techniques are implemented, -including Delaunay triangulation. Delaunay triangulation is defined as -follow: ‘for a set `S` of points in the Euclidean plane, the unique -triangulation `DT(S)` of `S` such that no point in `S` is inside the -circum-circle of any triangle in `DT(S)`. `DT(S)` is the dual of the -Voronoï diagram of `S`. If n is the number of points in `S`, the -Voronoï diagram of S is the partitioning of the plane containing `S` -points into n convex polygons such that each polygon contains exactly -one point and every point in a given polygon is closer to its central -point than to any other. A Voronoï diagram is sometimes also known as -a Dirichlet tessellation. - -The **`TGraph2D`** class has the following constructors: - -- With an arrays' dimension `n` and three arrays `x`, `y`, and `z` - (can be arrays of doubles, floats, or integers): - -``` {.cpp} - TGraph2D *g = new TGraph2D(n,x,y,z); -``` - -- With an array dimension only: - -``` {.cpp} - TGraph2D *g = new TGraph2D(n); -``` - -- Internal arrays are filled with the method `SetPoint` at the - position "`i`" with the values `x`, `y`, `z`: - -``` {.cpp} - g->SetPoint(i,x,y,z); -``` - -- Without parameters; the method `SetPoint` must be used to fill the - internal arrays. - -``` {.cpp} - TGraph2D *g = new TGraph2D(); -``` - -- From a file: - -``` {.cpp} - TGraph2D *g = new TGraph2D("graph.dat"); -``` - -The arrays are read from the ASCII file "`graph.dat`" according to a -specified format. The format's default value is "`%lg %lg %lg`". Note -that in any of last three cases, the `SetPoint` method can be used to -change a data point or to add a new one. If the data point index (`i`) -is greater than the size of the internal arrays, they are -automatically extended. - -Specific drawing options can be used to paint a **`TGraph2D`**: - -- "`TRI`" the Delaunay triangles are drawn using filled area. A - hidden surface drawing technique is used. The surface is painted - with the current fill area color. The edges of the triangles are - painted with the current line color; - -- "`TRIW`"the Delaunay triangles are drawn as wire frame; - -- "`TRI1`" the Delaunay triangles are painted with color levels. The - edges of the triangles are painted with the current line color; - -- "`TRI2`" the Delaunay triangles are painted with color levels; - -- "`P`"draws a marker at each vertex; - -- "`P0`" draws a circle at each vertex. Each circle background is - white. - -A **`TGraph2D`** can be also drawn with ANY options valid for 2D -histogram drawing. In this case, an intermediate 2D histogram is -filled using the Delaunay triangles technique to interpolate the data -set. **`TGraph2D`** linearly interpolate a `Z` value for any `(X,Y)` -point given some existing `(X,Y,Z)` points. The existing `(X,Y,Z)` -points can be randomly scattered. The algorithm works by joining the -existing points to make Delaunay triangles in `(X,Y)`. These are then -used to define flat planes in `(X,Y,Z)` over which to interpolate. The -interpolated surface thus takes the form of tessellating triangles at -various angles. Output can take the form of a 2D histogram or a -vector. The triangles found can be drawn in 3D. This software cannot -be guaranteed to work under all circumstances. It was originally -written to work with a few hundred points in an` XY` space with -similar `X` and `Y` ranges. - -![Graph2D drawn with option "surf1" and "tri1 p0"](pictures/0300005A.png) - -``` {.cpp} -{ - TCanvas *c = new TCanvas("c","Graph2D example",0,0,700,600); - Double_t x, y, z, P = 6.; - Int_t np = 200; - TGraph2D *dt = new TGraph2D(); - TRandom *r = new TRandom(); - - for (Int_t N=0; NRndm(N))-P; - y = 2*P*(r->Rndm(N))-P; - z = (sin(x)/x)*(sin(y)/y)+0.2; - dt->SetPoint(N,x,y,z); - } - gStyle->SetPalette(55); - dt->Draw("surf1"); // use "surf1" to generate the left picture -} // use "tri1 p0" to generate the right one -``` - -A more complete example is `$ROOTSYS/tutorials/math/fit/graph2dfit.C` that -produces the next figure. - -![Output of macro graph2dfit.C](pictures/0300005C.png) - -## TGraph2DErrors - - -A **`TGraph2DErrors`** is a **`TGraph2D`** with errors. It is useful to -perform fits with errors on a 2D graph. An example is the macro -`$ROOTSYS/tutorials/visualisation/graphs/gr011_graph2d_errorsfit.C`. - -## Fitting a Graph - - -The graph `Fit` method in general works the same way as the `TH1::Fit`. -See "Fitting Histograms". - -## Setting the Graph's Axis Title - - -To give the axis of a graph a title you need to draw the graph first, -only then does it actually have an axis object. Once drawn, you set the -title by getting the axis and calling the `TAxis::SetTitle` method, and -if you want to center it, you can call the `TAxis::CenterTitle` method. - -Assuming that `n, x,` and `y` are defined. Next code sets the titles of -the `x` and `y` axes. - -``` {.cpp} -root[] gr5 = new TGraph(n,x,y) -root[] gr5->Draw() -: created default TCanvas with name c1 -root[] gr5->Draw("ALP") -root[] gr5->GetXaxis()->SetTitle("X-Axis") -root[] gr5->GetYaxis()->SetTitle("Y-Axis") -root[] gr5->GetXaxis()->CenterTitle() -root[] gr5->GetYaxis()->CenterTitle() -root[] gr5->Draw("ALP") -``` - -For more graph examples see the scripts: `$ROOTSYS/tutorials` directory -`gr001_simple.C`, `gr002_errors.C`, `gr303_zdemo.C`, and `gr003_errors2.C`. - -![A graph with axis titles](pictures/0300005D.png) - -## Zooming a Graph - - -To zoom a graph you can create a histogram with the desired axis range -first. Draw the empty histogram and then draw the graph using the -existing axis from the histogram. - -``` {.cpp} -{ - c1 = new TCanvas("c1","A Zoomed Graph",200,10,700,500); - hpx = new TH2F("hpx","Zoomed Graph Example",10,0,0.5,10,1.0,8.0); - hpx->SetStats(kFALSE); // no statistics - hpx->Draw(); - Int_t n = 10; - Double_t x[n] = {-.22,.05,.25,.35,.5,.61,.7,.85,.89,.95}; - Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; - gr = new TGraph(n,x,y); - gr->SetMarkerColor(4); - gr->SetMarkerStyle(20); - gr->Draw("LP");// and draw it without an axis -} -``` - -The next example is the same graph as above with a zoom in the x and y -directions. - -![A zoomed graph](pictures/0300005E.png) - -## The User Interface for Graphs - - -The class **`TGraphEditor`** provides the user interface for setting -the following graph attributes interactively: - -- Title text entry field ... sets the title of the graph. - -- Shape radio button group - sets the graph shapes: - - - *No Line*: draw unconnected points; - - *Smooth Line*: a smooth curve; - - *Simple Line*: a simple poly-line; - - *Bart Chart*: a bar chart at each point. - - *Fill Area*: a fill area is drawn. - -- Show Marker - sets markers as visible or invisible. - -- Exclusion Zone - specifies the exclusion zone parameters : - - - *'+-‘ check button*: sets on which side of the line the - exclusion zone will be drawn; - - *Width combo box*: defines the width of the zone. - -![](pictures/0300005F.png) - diff --git a/documentation/users-guide/HTMLDoc.md b/documentation/users-guide/HTMLDoc.md deleted file mode 100644 index 252d3913cfd3e..0000000000000 --- a/documentation/users-guide/HTMLDoc.md +++ /dev/null @@ -1,311 +0,0 @@ -# Automatic HTML Documentation -\index{documentation!class} - - -**`THtml`** is ROOT's documentation engine. It can be used to document -your classes in a reference guide, and to convert your text or source -files to HTML. - -## Reference Guide - - -The Reference Guide for the ROOT classes at - has been generated by ROOT's -**`THtml`** class. Just as for ROOT's classes, it can generate (and -update) a reference guide for your classes, too. You document your -classes using source code comments. All comments will be automatically -put into a `
` environment to keep the indentation and line
-length. You can write "raw" HTML by enclosing comments in the keywords
-`Begin_Html` and `End_Html`.
-
-To generate documentation for the class **`TObject`** you could run the
-following commands:
-
-``` {.cpp}
-root[] THtml h
-root[] h.SetInputDir("$(ROOTSYS)");
-root[] h.MakeClass("TObject");
-root[] h.CreateJavascript();
-root[] h.CreateStylesheet();
-```
-
-The comments following the first comment of the form
-//\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_, before any method, is
-assumed to be the **class description**. As with any other documentation
-part, it has to be a continuous block of comments.
-
-Any documented class will have an **class index entry** in the
-`ClassIndex.html`, showing their name with a link to their documentation
-page and a miniature description. This description for e.g. the class
-`MyClass` has to be given in `MyClass's` header file as documentation.
-
-A **method description** block starts immediately after '`{`' and looks
-like this:
-
-``` {.cpp}
-void TWorld::HelloWorldFunc(string *text)
-{
-// This is a documentation example of the function TWorld::HelloWorldFunc
-helloWorld.Print(text);
-}
-```
-
-Like in a class description block, everything until the first
-non-commented line is considered as a valid member function description
-block.
-
-**Data members** are documented by putting a C++ comment behind their
-declaration in the header file, e.g.
-
-``` {.cpp}
-Int_t fIAmADataMember; // this is a data member
-```
-
-When documenting a class, **`THtml`** creates both a "beautified"
-version of the source file and a web page containing the class
-documentation. The documentation also shows the **author** and a
-**copyright statement**. This information is extracted from the source
-file. The author can be in the format
-
-``` {.cpp}
-// Author: Enrico Fermi
-```
-
-for people that have an entry in CERN's XWho database, and for those who
-have not:
-
-``` {.cpp}
-// Author: Enrico Fermi 
-```
-
-The copyright statement is introduced by the string "`* Copyright`"
-inside a comment.
-
-You should read the class reference page at
- to learn about all of
-**`THtml`**'s features.
-
-### Product and Module Documentation
-
-
-For **`THtml`**, a product like ROOT is a combination of several
-modules. It can include user-provided document for both products and
-modules. The name of the product can be set by calling
-`THtml::SetProductName()`. By default, the documentation is searched for
-in the `doc/` subdirectory of the source tree, and in the
-`../doc `directory, relative to the directory of first source file of a
-module. This can be set by calls to `THtml::SetProductDocDir()` and
-`THtml::SetModuleDocPath()`.
-
-The documentation is generated as an index page with links to further
-files. This index page includes the file `index.txt` converted to HTML
-(via `THtml::Convert()`) or the file index.html (without conversion to
-HTML, of course), if any of these files exist. The index page will also
-contain a list of links to all files in the directory that end on
-`.html` or `.txt`. Files ending on `.txt` will be converted to HTML
-before they are copied to the output directory. For each file, the
-link's text will be the file name without extension, with underscores
-replaced by spaces.
-
-You can see an example of the module documentation including links, the
-corresponding `index.html`, and the module class index at
-.
-
-## Converting Sources (and Other Files) to HTML
-
-
-**`THtml`** can take a file (C++ or text) and convert it to HTML. There
-are two main use cases:
-
-The output of a **macro** converted to HTML will almost look like the
-beautified source file of a class reference. The `Begin_Html/End_Html`
-keywords are supported; comments, strings, and keywords are colored like
-in **`THtml`**'s output for source code.
-
-The macro `Event.cxx` in `$ROOTSYS/test` can be seen as an example of
-documented ROOT macros at
-
-
-`THtml::Convert()`converts a single text file to HTML. For example, it
-can be run on a change log. Each known class name will be linked to its
-documentation page. An example is ROOT's change log at
-
-
-To convert the source file MyCode.C to HTML, you can run
-
-``` {.cpp}
-root[] THtml h
-root[] h.Convert("MyCode.C", "Look At My Code", "htmlout/");
-```
-
-This will create the file `htmlout/MyCode.C.html`. The HTML page will
-have the title "Look At My Code".
-
-## Special Documentation Elements: Directives
-
-
-A common documentation problem is the inclusion of images. They are
-usually generated externally, which poses problems with where to keep
-the images, and how to keep them up to date. **`THtml`** solves this by
-offering a few special documentation elements: macro and latex
-directives.
-
-### Latex Directive
-
-
-Documentation surrounded by the keywords `BEGIN_LATEX / END_LATEX` will
-be passed to ROOT Latex engine **`TLatex`**. The keywords can be written
-with small or capital letters (case insensitive). The output will be
-stored to an image file, which gets automatically included in the
-documentation.
-
-``` {.cpp}
-// This function calculates BEGIN_LATEX
-//   F(x_{#frac{1}{2}}) = #prod(x < x_{#frac{1}{2}}) = #frac{1}{2}
-// END_LATEX
-```
-
-THtml will inject the following picture:
-
-![](pictures/0300022D.png)
-
-The image file name is generated from the formula and will be unique for
-all the documentation. It is stored along-side the documentation, and it
-will be automatically regenerated when the documentation is updated. The
-handling of the Latex directive is done by the class
-**`TDocLatexDirective`**.
-
-The `BEGIN_LATEX` keyword can take the following parameters:
-
--   `fontsize`: sets the **`TLatex`** font size. The default value is 16.
-
--   `separator`: sets a list of characters for which a new column will
-    be started. This allows aligned, multi-line, multi-column layout,
-    which can be useful for e.g. mathematical derivations. It is unset
-    by default, meaning the Latex directive will only generate one
-    column.
-
--   `rseparator`: like separator, but a regular expression. Columns
-    start with a match of this regular expression. Only one of separator
-    or rseparator can be given.
-
--   `align`: defines the alignment of the columns. Note that the column
-    delimiter counts as a column itself!
-
-Example invocation, where the font size is set to 10, new columns are
-started by the characters '`=`' and '`,`', and the two columns are left
-aligned with the separator column centered:
-
-`Begin_Latex(fontsize=10, separator='=,', align=lcl)`
-
-### Macro Directive
-
-
-A more general approach is offered by the Macro directive, enclosed in
-the keywords `BEGIN_MACRO /` `END_MACRO`. The keywords can be written
-with small or capital letters (case insensitive). If the text enclosed
-by these keywords contains the character '`{`' the text is assumed to be
-source code. Otherwise it is assumed to be a file name relative to the
-current file's path, and taking into account the paths specified by
-**`THtml::AddMacroPath()`. The macro file or the C++ source is executed
-when generating the documentation. It is expected to return a
-**`TObject*`**, which will be saved to a GIF file, by calling the
-virtual function **`TObject::SaveAs()`.****
-
-The `BEGIN_MACRO` keyword can take the following parameters:
-
--   `GUI`: will end batch mode. This is needed e.g. for creating screen
-    shots of GUI elements, where the call to **`TObject::SaveAs()` will
-    invoke `TGObject`**`::SaveAs()` which needs the graphics system to
-    be initialized.
-
--   `source`: requests the source of the macro to be shown in a second
-    tab on the HTML page. This is useful e.g. for example macros,
-    showing how the image was generated. Lines that should be executed
-    but not shown in the source tab can be hidden by ending them with
-    `*HIDE*` (most probably as a comment). Lines may be hidden because
-    they are not needed for the understanding of the macro or because
-    they only make sense in the context of the documentation, like the
-    statement returning the **`TObject*`**.
-
-Example invocation, with enabled ROOT graphics system and a source tab:
-
-`Begin_Macro(gui, source)`
-
-## Customizing HTML
-
-
-**`THtml`** allows a vast amount of customizations, from a custom style
-to custom links, to customized java scripts. By default, the style sheet
-is taken from `$ROOTSYS/etc/html/ROOT.css` when the documentation is
-generated. The path for `ROOT.css` can be changed by calling
-`THtml::SetEtcDir()`; it should contain the same CSS classes and entity
-IDs as the original `ROOT.css`. This style sheet is an easy means of
-customizing the layout and appearance of the documentation pages. Many
-of **`THtml`** setting can be customized by calls to **`THtml`** member
-functions or by settings in .rootrc, as documented in the **`THtml`**
-class reference page . The
-following will enumerate some of the highlights.
-
-### Referencing Documentation for other Libraries
-
-
-When **`THtml`** generates documentation for classes it recognizes all
-class names known to ROOT. If **`THtml`** does not have sources for a
-class it determines the class's library name. This has to be set by
-means of `rootmap` files, see Library AutoLoading of this User's Guide.
-Given the library name, **`THtml`** searches for an entry in its map of
-libraries to documentation URLs. If it finds it, it will create a link
-to the documentation at that URL for all occurrences of a given class
-name. One can set the URL `../mylib/` for a library name `MyLib` by
-setting `Root.Html.MyLib:` `../mylib/` or by calling
-`THtml::SetLibURL("MyLib", "../mylib/")`. Occurrences of class `MyClass`
-of `MyLib` will now be referenced as `../mylib/MyClass.html`.
-
-### Search Engine
-
-
-**`THtml`** can invoke external search engines. The ROOT reference guide
-sets `Root.Html.Search` to .
-Calling **`THtml::SetSearchStemURL()`** will set the same. If this URL stem is
-set, `THtml` will create search fields in the index pages. It will
-send the words entered in these search fields as %s in the URL; %u will
-be replaced by the current document's path, allowing a site- and
-directory-specific search.
-
-### ViewCVS
-
-
-Most code is managed in a version control system like CVS. ViewCVS is a
-WWW reader interface to the versioning control system that allows e.g.
-tracking a file's changes. **`THtml`** will reference these pages
-automatically if the `.rootrc` variable `Root.Html.ViewCVS` is set to
-the URL stem of the ViewCVS. installation. Alternatively, one can call
-THtml::SetViewCVS().
-
-### Wiki Pages
-
-
-In some contexts it might be desirable to let users comment on classes,
-e.g. for suggestions of use or alternatives, details of behavior, and
-cross references to other relevant classes. A successful example of this
-is the PHP.net documentation with its user annotations. **`THtml`** can
-include a link to a class's Wiki page by setting the Wiki base URL via
-`Root.Html.WikiURL` or **`THtml`**`::SetWikiURL()`.
-
-## Tutorial
-
-
-You can run the tutorial `htmlex.C` to see how **`THtml`** converts a
-script to HTML and how it creates the corresponding class reference:
-
-``` {.cpp}
-root[] .x $(ROOTSYS)/tutorials/htmlex.C+
-```
-
-Have a look at the HTML version of the macro in
-`htmldoc/htmlex.C.html `(which should be the same as the one at
-).
-
-It demonstrates how to generate documentation for your classes and for
-ROOT classes and how to "beautify" a macro.
diff --git a/documentation/users-guide/Histograms.md b/documentation/users-guide/Histograms.md
deleted file mode 100644
index 3921f52964aad..0000000000000
--- a/documentation/users-guide/Histograms.md
+++ /dev/null
@@ -1,2365 +0,0 @@
-# Histograms
-
-
-This chapter covers the functionality of the histogram classes. We
-begin with an overview of the histogram classes, after which we
-provide instructions and examples on the histogram features.
-
-We have put this chapter ahead of the graphics chapter so that you can
-begin working with histograms as soon as possible. Some of the
-examples have graphics commands that may look unfamiliar to you. These
-are covered in the chapter "Input/Output".
-
-## The Histogram Classes
-\index{histogram}
-
-ROOT supports histograms up to three dimensions. Separate concrete
-classes are provided for one-dimensional, two-dimensional and
-three-dimensional classes. The histogram classes are split into
-further categories, depending on the set of possible bin values:
-
--   **`TH1C, TH2C and TH3C`** contain one char (one byte) per bin
-    (maximum bin content = 255)
-
--   **`TH1S, TH2S and TH3S`** contain one short (two bytes) per bin
-    (maximum bin content = 65 535).
-
--   **`TH1I, TH2I and TH3I`** contain one integer (four bytes) per bin
-    (maximum bin content = 2 147 483 647).
-
--   **`TH1L, TH2L and TH3L`** contain one long64 (eight bytes) per bin
-    (maximum bin content = 9 223 372 036 854 775 807).
-
--   **`TH1F, TH2F and TH3F`** contain one float (four bytes) per bin
-    (maximum precision = 7 digits).
-
--   **`TH1D, TH2D and TH3D`** contain one double (eight bytes) per bin
-    (maximum precision = 14 digits).
-
-ROOT also supports profile histograms, which constitute an elegant
-replacement of two-dimensional histograms in many cases. The
-inter-relation of two measured quantities X and Y can always be
-visualized with a two-dimensional histogram or scatter-plot. Profile
-histograms, on the other hand, are used to display the mean value of Y
-and its RMS for each bin in X. If Y is an unknown but single-valued
-approximate function of X, it will have greater precision in a profile
-histogram than in a scatter plot.
-
--   **`TProfile`** : one dimensional profiles
-
--   **`TProfile2D`** : two dimensional profiles
-
-![The class hierarchy of histogram classes](pictures/0600002E.png)
-
-All ROOT histogram classes are derived from the base class **`TH1`**
-(see figure above). This means that two-dimensional and
-three-dimensional histograms are seen as a type of a one-dimensional
-histogram, in the same way in which multidimensional C arrays are just
-an abstraction of a one-dimensional contiguous block of memory.
-
-## Creating Histograms
-
-
-There are several ways in which you can create a histogram object in
-ROOT. The straightforward method is to use one of the several
-constructors provided for each concrete class in the histogram
-hierarchy. For more details on the constructor parameters, see the
-subsection ["Constant or Variable Bin
-Width"](#Fixed.or.Variable.Bin.Width) below. Histograms may also be
-created by:
-
--   Calling the Clone() method of an existing histogram
-
--   Making a projection from a 2-D or 3-D histogram
-
--   Reading a histogram from a file (see Input/Output chapter)
-
-``` {.cpp}
-   // using various constructors
-   TH1* h1 = new TH1I("h1", "h1 title", 100, 0.0, 4.0);
-   TH2* h2 = new TH2F("h2", "h2 title", 40, 0.0, 2.0, 30, -1.5, 3.5);
-   TH3* h3 = new TH3D("h3", "h3 title", 80, 0.0, 1.0, 100, -2.0, 2.0,
-                       50, 0.0, 3.0);
-
-   // cloning a histogram
-   TH1* hc = (TH1*)h1->Clone();
-
-   // projecting histograms
-   // the projections always contain double values !
-   TH1* hx = h2->ProjectionX(); // ! TH1D, not TH1F
-   TH1* hy = h2->ProjectionY(); // ! TH1D, not TH1F
-```
-
-### Constant or Variable Bin Width
-
-
-The histogram classes provide a variety of ways to construct a
-histogram, but the most common way is to provide the name and title of
-histogram and for each dimension: the number of bins, the minimum x
-(lower edge of the first bin) and the maximum x (upper edge of the
-last bin).
-
-``` {.cpp}
-   TH2* h = new TH2D(
-      /* name */ "h2",
-      /* title */ "Hist with constant bin width",
-      /* X-dimension */ 100, 0.0, 4.0,
-      /* Y-dimension */ 200, -3.0, 1.5);
-```
-
-When employing this constructor, you will create a histogram with
-constant (fixed) bin width on each axis. For the example above, the
-interval `[0.0, 4.0]` is divided into 100 bins of the same width `w`
-`X = 4.0 - 0.0 100 = 0.04` for the X axis (dimension). Likewise, for
-the Y axis (dimension), we have bins of equal width `w`
-`Y = 1.5 - (-3.0) 200 = 0.0225`.
-
-If you want to create histograms with variable bin widths, ROOT
-provides another constructor suited for this purpose. Instead of
-passing the data interval and the number of bins, you have to pass an
-array (single or double precision) of bin edges. When the histogram
-has `n` bins, then there are `n+1` distinct edges, so the array you
-pass must be of size `n+1`.
-
-``` {.cpp}
-   const Int_t NBINS = 5;
-   Double_t edges[NBINS + 1] = {0.0, 0.2, 0.3, 0.6, 0.8, 1.0};
-   // Bin 1 corresponds to range [0.0, 0.2]
-   // Bin 2 corresponds to range [0.2, 0.3] etc...
-
-   TH1* h = new TH1D(
-      /* name */ "h1",
-      /* title */ "Hist with variable bin width",
-      /* number of bins */ NBINS,
-      /* edge array */ edges
-    );
-```
-
-Each histogram object contains three **`TAxis`** objects: `fXaxis` ,
-`fYaxis,` and `fZaxis`, but for one-dimensional histograms only the
-X-axis is relevant, while for two-dimensional histograms the X-axis
-and Y-axis are relevant. See the class **` TAxis`** for a description
-of all the access methods. The bin edges are always stored internally
-in double precision.
-
-You can examine the actual edges / limits of the histogram bins by
-accessing the axis parameters, like in the example below:
-
-``` {.cpp}
-   const Int_t XBINS = 5; const Int_t YBINS = 5;
-   Double_t xEdges[XBINS + 1] = {0.0, 0.2, 0.3, 0.6, 0.8, 1.0};
-   Double_t yEdges[YBINS + 1] = {-1.0, -0.4, -0.2, 0.5, 0.7, 1.0};
-
-   TH2* h = new TH2D("h2", "h2", XBINS, xEdges, YBINS, yEdges);
-   TAxis* xAxis = h->GetXaxis(); TAxis* yAxis = h->GetYaxis();
-
-   cout << "Third bin on Y-dimension: " << endl; // corresponds to
-                                                 // [-0.2, 0.5]
-   cout << "\tLower edge: " << yAxis->GetBinLowEdge(3) << endl;
-   cout << "\tCenter: " << yAxis->GetBinCenter(3) << endl;
-   cout << "\tUpper edge: " << yAxis->GetBinUpEdge(3) << endl;
-```
-
-## Bin Numbering
-
-
-All histogram types support fixed or variable bin sizes. 2-D
-histograms may have fixed size bins along X and variable size bins
-along Y or vice-versa. The functions to fill, manipulate, draw, or
-access histograms are identical in both cases.
-
-### Convention
-
-
-For all histogram types: `nbins` , `xlow` , `xup`
-
-Bin\# 0 contains the underflow.
-
-Bin\# 1 contains the first bin with low-edge ( `xlow` INCLUDED).
-
-The second to last bin (bin\# `nbins`) contains the upper-edge
-(`xup` EXCLUDED).
-
-The Last bin (bin\# `nbins+1)` contains the overflow.
-
-In case of 2-D or 3-D histograms, a "global bin" number is defined.
-For example, assuming a 3-D histogram `h` with `binx`, `biny`, `binz`,
-the function  returns a global/linear bin number.
-
-``` {.cpp}
-   Int_t bin = h->GetBin(binx, biny, binz);
-```
-
-This global bin is useful to access the bin information independently
-of the dimension.
-
-### Re-binning
-\index{histogram!rebin}
-
-At any time, a histogram can be re-binned via the **`TH1`**`::Rebin()`
-method. It returns a new histogram with the re-binned contents. If bin
-errors were stored, they are recomputed during the re-binning.
-
-## Filling Histograms
-
-
-A histogram is typically filled with statements like:
-
-``` {.cpp}
-   h1->Fill(x);
-   h1->Fill(x,w); // with weight
-   h2->Fill(x,y);
-   h2->Fill(x,y,w);
-   h3->Fill(x,y,z);
-   h3->Fill(x,y,z,w);
-```
-
-The `Fill` method computes the bin number corresponding to the given
-x, y or z argument and increments this bin by the given weight. The
-`Fill()` method returns the bin number for 1-D histograms or global
-bin number for 2-D and 3-D histograms. If **`TH1`**`::Sumw2()` has
-been called before filling, the sum of squares is also stored. One can
-increment a bin number directly by calling
-**`TH1`**`::AddBinContent()`, replace the existing content via
-**`TH1`**`::SetBinContent()` , and access the bin content of a given
-bin via **`TH1`**`::GetBinContent()` .
-
-``` {.cpp}
-   Double_t binContent = h->GetBinContent(bin);
-```
-
-### Automatic Re-binning Option
-
-
-By default, the number of bins is computed using the range of the
-axis. You can change this to re-bin automatically by setting the
-automatic re-binning option:
-
-``` {.cpp}
-   h->SetBit(TH1::kCanRebin);
-```
-\index{histogram!rebin}
-
-
-Once this is set, the `Fill()` method will automatically extend the
-axis range to accommodate the new value specified in the `Fill()`
-argument. The used method is to double the bin size until the new
-value fits in the range, merging bins two by two. The
-**`TTree`**`::Draw()` method extensively uses this automatic binning
-option when drawing histograms of variables in **`TTree`** with an
-unknown range. The automatic binning option is supported for 1-D, 2-D
-and 3-D histograms. During filling, some statistics parameters are
-incremented to compute the mean value and root mean square with the
-maximum precision. In case of histograms of type **`TH1C`**,
-**`TH1S`**, **`TH2C`**, **`TH2S`**, **`TH3C`**, **`TH3S`** a check is
-made that the bin contents do not exceed the maximum positive capacity
-(127 or 65 535). Histograms of all types may have positive or/and
-negative bin contents.
-
-## Random Numbers and Histograms
-
-
-**`TH1`**`::FillRandom()` can be used to randomly fill a histogram
-using the contents of an existing **`TF1`** function or another
-**`TH1`** histogram (for all dimensions). For example, the following
-two statements create and fill a histogram 10 000 times with a default
-Gaussian distribution of `mean` `0` and `sigma` `1` :
-
-``` {.cpp}
-root[] TH1F h1("h1","Histo from a Gaussian",100,-3,3);
-root[] h1.FillRandom("gaus",10000);
-```
-
-**`TH1`**`::GetRandom()` can be used to get a random number
-distributed according the contents of a histogram. To fill a histogram
-following the distribution in an existing histogram you can use the
-second signature of **`TH1`**`::FillRandom()`. Next code snipped
-assumes that `h` is an existing histogram (**`TH1`** ).
-
-``` {.cpp}
-root[] TH1F h2("h2","Histo from existing histo",100,-3,3);
-root[] h2.FillRandom(&h1, 1000);
-```
-
-The distribution contained in the histogram `h1` ( **`TH1`** ) is
-integrated over the channel contents. It is normalized to one. The
-second parameter (1000) indicates how many random numbers are
-generated.
-
-Getting 1 random number implies:
-
--   Generating a random number between 0 and 1 (say `r1` )
-
--   Find the bin in the normalized integral for `r1`
-
--   Fill histogram channel
-
-You can see below an example of the **`TH1`**`::GetRandom()` method
-which can be used to get a random number distributed according
-the contents of a histogram.
-
-``` {.cpp}
-void getrandomh() {
-   TH1F *source = new TH1F("source","source hist",100,-3,3);
-   source->FillRandom("gaus",1000);
-   TH1F *final = new TH1F("final","final hist",100,-3,3);
-
-             // continued...
-
-   for (Int_t i=0;i<10000;i++) {
-      final->Fill(source->GetRandom());
-   }
-   TCanvas *c1 = new TCanvas("c1","c1",800,1000);
-   c1->Divide(1,2);
-   c1->cd(1);
-   source->Draw();
-   c1->cd(2);
-   final->Draw();
-   c1->cd();
-}
-```
-
-## Adding, Dividing, and Multiplying
-
-
-Many types of operations are supported on histograms or between
-histograms:
-
--   Addition of a histogram to the current histogram
-
--   Additions of two histograms with coefficients and storage into the
-    current histogram
-
--   Multiplications and divisions are supported in the same way as
-    additions.
-
--   The `Add` , `Divide` and ` Multiply` methods also exist to add,
-    divide or multiply a histogram by a function.
-
-Histograms objects (not pointers) **`TH1F`** `h1` can be multiplied by
-a constant using:
-
-``` {.cpp}
-   h1.Scale(const)
-```
-
-A new histogram can be created without changing the original one by
-doing:
-
-``` {.cpp}
-   TH1F h3 = 8*h1;
-```
-
-To multiply two histogram objects and put the result in a 3rd one do:
-
-``` {.cpp}
-   TH1F h3 = h1*h2;
-```
-
-The same operations can be done with histogram pointers
-**`TH1F`** `*h1`, **`*h2`** following way:
-
-``` {.cpp}
-   h1->Scale(const) TH1F h3 = 8*(*h1); TH1F h3 = (*h1)*(*h2);
-```
-
-Of course, the **`TH1`** methods `Add` , `Multiply` and `Divide` can
-be used instead of these operators.
-
-If a histogram has associated error bars ( **`TH1`**`::Sumw2()` has
-been called), the resulting error bars are also computed assuming
-independent histograms. In case of divisions, binomial errors are also
-supported.
-
-## Projections
-
-
-One can make:
-
--   a 1-D projection of a 2-D histogram or profile. See
-    **`TH2`**`::ProfileX`,
-    **`TH2`**`::ProfileY, `**`TProfile`**`::ProjectionX`,
-    **`TProfile2D`**`::ProjectionXY`, **`TH2`**`::ProjectionX`,
-    **`TH2`**`::ProjectionY` .
-
--   a 1-D, 2-D or profile out of a 3-D histogram see
-    **`TH3`**`::ProjectionZ`, **`TH3`**`::Project3D`.
-
-These projections can be fit via: **`TH2`**`::FitSlicesX`,
-**`TH2`**`::FitSlicesY`, **`TH3`**`::FitSlicesZ`.
-
-## Drawing Histograms
-
-
-When you call the `Draw` method of a histogram ( **`TH1`**` ::Draw` )
-for the first time, it creates a **`THistPainter`** object and saves a
-pointer to painter as a data member of the histogram. The
-**`THistPainter`** class specializes in the drawing of histograms. It
-allows logarithmic axes (x, y, z) when the CONT drawing option is
-using. The **`THistPainter`** class is separated from the histogram so
-that one can have histograms without the graphics overhead, for
-example in a batch program. The choice to give each histogram has its
-own painter rather than a central singleton painter, allows two
-histograms to be drawn in two threads without overwriting the
-painter's values. When a displayed histogram is filled again, you do
-not have to call the `Draw` method again. The image is refreshed the
-next time the pad is updated. A pad is updated after one of these
-three actions:
-
--   A carriage control on the ROOT command line
-
--   A click inside the pad
-
--   A call to **`TPad`**`::Update()`
-
-By default, the **`TH1`**`::Draw` clears the pad before drawing the
-new image of the histogram. You can use the `"SAME"` option to leave
-the previous display intact and superimpose the new histogram. The
-same histogram can be drawn with different graphics options in
-different pads. When a displayed histogram is deleted, its image is
-automatically removed from the pad. To create a copy of the histogram
-when drawing it, you can use **`TH1`**`::DrawClone()`. This will clone
-the histogram and allow you to change and delete the original one
-without affecting the clone. You can use **`TH1`**`::DrawNormalized()`
-to draw a normalized copy of a histogram.
-
-``` {.cpp}
-TH1 *TH1::DrawNormalized(Option_t *option,Double_t norm) const
-```
-
-A clone of this histogram is normalized to norm and drawn with option.
-A pointer to the normalized histogram is returned. The contents of the
-histogram copy are scaled such that the new sum of weights (excluding
-under and overflow) is equal to `norm` .
-
-Note that the returned normalized histogram is not added to the list
-of histograms in the current directory in memory. It is the user's
-responsibility to delete this histogram. The `kCanDelete` bit is set
-for the returned object. If a pad containing this copy is cleared, the
-histogram will be automatically deleted. See "Draw Options" for the
-list of options.
-
-### Setting the Style
-
-
-Histograms use the current style ***`gStyle`***, which is the global
-object of class **`TStyle`**. To change the current style for
-histograms, the **`TStyle`** class provides a multitude of methods
-ranging from setting the fill color to the axis tick marks. Here are
-a few examples:
-
-``` {.cpp}
-   void SetHistFillColor(Color_t color = 1)
-   void SetHistFillStyle(Style_t styl = 0)
-   void SetHistLineColor(Color_t color = 1)
-   void SetHistLineStyle(Style_t styl = 0)
-   void SetHistLineWidth(Width_t width = 1)
-```
-
-When you change the current style and would like to propagate the
-change to a previously created histogram you can call
-**`TH1`**`::UseCurrentStyle()`. You will need to call
-`UseCurrentStyle()` on each histogram. When reading many histograms
-from a file and you wish to update them to the current style, you can
-use ***`gROOT`***`::ForceStyle` and all histograms read after this
-call will be updated to use the current style. See "Graphics and the
-Graphical User Interface". When a histogram is automatically created
-as a result of a **`TTree`**`::Draw` , the style of the histogram is
-inherited from the tree attributes and the current style is ignored.
-The tree attributes are the ones set in the current **`TStyle`** at
-the time the tree was created. You can change the existing tree to use
-the current style, by calling **`TTree`**`::UseCurrentStyle()` .
-
-### Draw Options
-
-
-The following draw options are supported on all histogram classes:
-
--   "`AXIS`": Draw only the axis.
-
--   "`HIST`": When a histogram has errors, it is visualized by default
-    with error bars. To visualize it without errors use `HIST`
-    together with the required option (e.g. "`HIST SAME C`").
-
--   "`SAME`": Superimpose on previous picture in the same pad.
-
--   "`CYL`": Use cylindrical coordinates.
-
--   "`POL`": Use polar coordinates.
-
--   "`SPH`": Use spherical coordinates.
-
--   "`PSR`": Use pseudo-rapidity/phi coordinates.
-
--   "`LEGO`": Draw a lego plot with hidden line removal.
-
--   "`LEGO1`": Draw a lego plot with hidden surface removal.
-
--   "`LEGO2`": Draw a lego plot using colors to show the cell
-               contents.
-
--   "`SURF`": Draw a surface plot with hidden line removal.
-
--   "`SURF1`": Draw a surface plot with hidden surface removal.
-
--   "`SURF2`": Draw a surface plot using colors to show the cell
-               contents.
-
--   "`SURF3`": Same as `SURF` with a contour view on the top.
-
--   "`SURF4`": Draw a surface plot using `Gouraud` shading.
-
--   "`SURF5`": Same as `SURF3` but only the colored contour is drawn.
-    Used with option `CYL` , `SPH` or `PSR` it allows to draw colored
-    contours on a sphere, a cylinder or in a pseudo rapidly space. In
-    Cartesian or polar coordinates, option `SURF3` is used.
-
-The following options are supported for 1-D histogram classes:
-
--   "`AH`": Draw the histogram, but not the axis labels and tick marks
-
--   "`B`": Draw a bar chart
-
--   "`C`": Draw a smooth curve through the histogram bins
-
--   "`E`": Draw the error bars
-
--   "`E0`": Draw the error bars including bins with 0 contents
-
--   "`E1`": Draw the error bars with perpendicular lines at the edges
-
--   "`E2`": Draw the error bars with rectangles
-
--   "`E3`": Draw a fill area through the end points of the vertical
-            error bars
-
--   "`E4`": Draw a smoothed filled area through the end points of the
-    error bars
-
--   "`L`": Draw a line through the bin contents
-
--   "`P`": Draw a (poly)marker at each bin using the histogram's
-    current marker style
-
--   "`P0`": Draw current marker at each bin including empty bins
-
--   "`PIE`": Draw a Pie Chart
-
--   "`*H`": Draw histogram with a \* at each bin
-
--   "`LF2`": Draw histogram as with option "`L`" but with a fill
-    area. Note that "`L`" also draws a fill area if the histogram fill
-    color is set but the fill area corresponds to the histogram
-    contour.
-
--   "`9`": Force histogram to be drawn in high resolution mode. By
-    default, the histogram is drawn in low resolution in case the
-    number of bins is greater than the number of pixels in the current
-    pad
-
--   "`][`": Draw histogram without the vertical lines for the first
-    and the last bin. Use it when superposing many histograms on the
-    same picture.
-
-The following options are supported for 2-D histogram classes:
-
--   "`ARR`": Arrow mode. Shows gradient between adjacent cells
-
--   "`BOX`": Draw a box for each cell with surface proportional to
-    contents
-
--   "`BOX1`": A sunken button is drawn for negative values, a raised
-    one for positive values
-
--   "`COL`": Draw a box for each cell with a color scale varying with
-    contents
-
--   "`COLZ`": Same as "`COL`" with a drawn color palette
-
--   "`CONT`": Draw a contour plot (same as `CONT0` )
-
--   "`CONTZ`": Same as "`CONT`" with a drawn color palette
-
--   "`CONT0`": Draw a contour plot using surface colors to distinguish
-    contours
-
--   "`CONT1`": Draw a contour plot using line styles to distinguish
-    contours
-
--   "`CONT2`": Draw a contour plot using the same line style for all
-    contours
-
--   "`CONT3`": Draw a contour plot using fill area colors
-
--   "`CONT4`": Draw a contour plot using surface colors
-    (`SURF2` option at theta = 0)
-
--   `"CONT5":` Use Delaunay triangles to compute the contours
-
--   "`LIST`": Generate a list of **`TGraph`** objects for each contour
-
--   "`FB`": To be used with `LEGO` or `SURFACE` , suppress the
-    Front-Box
-
--   "`BB`": To be used with `LEGO` or `SURFACE` , suppress the
-    Back-Box
-
--   "`A`": To be used with `LEGO` or `SURFACE` , suppress the axis
-
--   "`SCAT`": Draw a scatter-plot (default)
-
--   "`SPEC`": Use **`TSpectrum2Painter`** tool for drawing
-
--   "`TEXT`": Draw bin contents as text
-    (format set via `gStyle->SetPaintTextFormat)` .
-
--   "`TEXTnn`": Draw bin contents as text at angle `nn` ( `0Draw("E1SAME");
-  h->Draw("e1same");
-```
-
-The options are not case sensitive. The options `BOX` , `COL` and
-`COLZ` use the color palette defined in the current style (see
-**`TStyle`**`::SetPalette`). The options `CONT` , `SURF` , and `LEGO`
-have by default 20 equidistant contour levels, you can change the
-number of levels with **`TH1`**`::SetContour`. You can also set the
-default drawing option with **`TH1`**`::SetOption` . To see the
-current option use **`TH1`**`::GetOption` . For example:
-
-``` {.cpp}
-   h->SetOption("lego");
-   h->Draw(); // will use the lego option
-   h->Draw("scat") // will use the scatter plot option
-```
-
-#### The SCATter Plot Option
-
-By default, 2D histograms are drawn as scatter plots. For each cell
-`(i,j)` a number of points proportional to the cell content are drawn.
-A maximum of 500 points per cell are drawn. If the maximum is above
-500 contents are normalized to 500.
-
-#### The ARRow Option
-
-The `ARR` option shows the gradient between adjacent cells. For each
-cell `(i,j)` an arrow is drawn. The orientation of the arrow follows
-the cell gradient.
-
-#### The BOX Option
-
-For each cell `(i,j)` a box is drawn with surface proportional to
-contents. The size of the box is proportional to the absolute value of
-the cell contents. The cells with negative contents are drawn with an
-X on top of the boxes. With option `BOX1` a button is drawn for each
-cell with surface proportional to contents' absolute value. A sunken
-button is drawn for negative values, a raised one for positive values.
-
-#### The ERRor Bars Options
-
--   `"E"` Default. Draw only error bars, without markers
-
--   `"E0"` Draw also bins with 0 contents (turn off the symbols
-    clipping).
-
--   `"E1"` Draw small lines at the end of error bars
-
--   `"E2"` Draw error rectangles
-
--   `"E3"` Draw a fill area through the end points of vertical error
-    bars
-
--   `"E4"` Draw a smoothed filled area through the end points of error
-    bars
-
-![The "E1" bars' option](pictures/0300002F.png)
-
-Note that for all options, the line and fill attributes of the
-histogram are used for the errors or errors contours. Use
-`gStyle->SetErrorX(dx)` to control the size of the error along x. The
-parameter `dx` is a percentage of bin width for errors along `X`. Set
-`dx=0` to suppress the error along `X`. Use
-`gStyle->SetEndErrorSize(np)` to control the size of the lines at the
-end of the error bars (when option 1 is used). By default `np=1`
-(`np` represents the number of pixels).
-
-#### The Color Option
-
-For each cell `(i,j)` a box is drawn with a color proportional to the
-cell content. The color table used is defined in the current style
-(***`gStyle`*** ). The color palette in **`TStyle`** can be modified
-with **`TStyle`**`::SetPalette` .
-
-![Different draw options](pictures/02000030.png)
-
-#### The TEXT Option
-
-For each cell `(i,j)` the cell content is printed. The text attributes
-are:
-
--   Text font = current font set by **`TStyle`**
-
--   Text size= 0.02 \* pad-height \* marker-size
-
--   Text color= marker color
-
-![The TEXT option](pictures/02000031.png)
-
-#### The CONTour Options
-
-The following contour options are supported:
-
--   `"CONT":` Draw a contour plot (same as CONT0)
-
--   `"CONT0":` Draw a contour plot using surface colors to distinguish
-    contours
-
--   `"CONT1":` Draw a contour plot using line styles to distinguish
-    contours
-
--   `"CONT2":` Draw a contour plot using the same line style for all
-    contours
-
--   `"CONT3":` Draw a contour plot using fill area colors
-
--   `"CONT4":`Draw a contour plot using surface colors (SURF2 option
-    at theta = 0); see also options "`AITOFF`", "`MERCATOR`", etc.
-    below
-
--   `"CONT5":` Use Delaunay triangles to compute the contours
-
-![Different contour options](pictures/02000032.png)
-
-The default number of contour levels is 20 equidistant levels. It can
-be changed with **`TH1`**`::SetContour`. When option "`LIST`" is
-specified together with option "`CONT`", all points used for contour
-drawing, are saved in the **`TGraph`** object and are accessible in
-the following way:
-
-``` {.cpp}
-   TObjArray *contours =
-      gROOT->GetListOfSpecials()->FindObject("contours");
-   Int_t ncontours = contours->GetSize(); TList *list =
-   (TList*)contours->At(i);
-```
-
-Where "`i`" is a contour number and list contains a list of
-**`TGraph`** objects. For one given contour, more than one disjoint
-poly-line may be generated. The **`TGraph`** numbers per contour are
-given by `list->GetSize()`. Here we show how to access the first graph
-in the list.
-
-``` {.cpp}
-   TGraph *gr1 = (TGraph*)list->First();
-```
-
--   "`AITOFF`": Draw a contour via an AITOFF projection
-
--   "`MERCATOR`": Draw a contour via a Mercator projection
-
--   "`SINUSOIDAL`": Draw a contour via a Sinusoidal projection
-
--   "`PARABOLIC`": Draw a contour via a Parabolic projection
-
-The tutorial macro `earth.C` uses these four options and produces the
-following picture:
-
-![The `earth.C` macro output](pictures/03000033.png)
-
-#### The LEGO Options
-
-In a lego plot, the cell contents are drawn as 3D boxes, with the
-height of the box proportional to the cell content.
-
-!["LEGO" and "SURF" options](pictures/02000034.png)
-
--   "`LEGO`": Draw a lego plot with hidden line removal
-
--   "`LEGO1`": Draw a lego plot with hidden surface removal
-
--   "`LEGO2`": Draw a lego plot using colors to show the cell contents
-
-A lego plot can be represented in several coordinate systems; the
-default system is Cartesian coordinates. Other possible coordinate
-systems are `CYL` , `POL` , `SPH` , and `PSR` .
-
--   "`CYL`": Cylindrical coordinates: x-coordinate is mapped on the
-    angle; y-coordinate - on the cylinder length.
-
--   "`POL`": Polar coordinates: x-coordinate is mapped on the angle;
-    y-coordinate - on the radius.
-
--   "`SPH`": Spherical coordinates: x-coordinate is mapped on the
-    latitude; y-coordinate - on the longitude.
-
--   "`PSR`": PseudoRapidity/Phi coordinates: x-coordinate is mapped on
-    Phi.
-
-With **`TStyle`**`::SetPalette` the color palette can be changed. We
-suggest you use palette 1 with the call:
-
-``` {.cpp}
-   gStyle->SetPalette(1);
-```
-
-#### The SURFace Options
-
-In a surface plot, cell contents are represented as a mesh. The height
-of the mesh is proportional to the cell content. A surface plot can be
-represented in several coordinate systems. The default is Cartesian
-coordinates, and the other possible systems are `CYL`, `POL`, `SPH`,
-and `PSR` . The following picture uses `SURF1` . With
-**`TStyle`**`::SetPalette` the color palette can be changed.
-We suggest you use palette 1 with the call:
-
-``` {.cpp}
-   gStyle->SetPalette(1);
-```
-
-![Different surface options](pictures/02000035.png)
-
--   "`SURF`": Draw a surface plot with hidden line removal
-
--   "`SURF1`": Draw a surface plot with hidden surface removal
-
--   "`SURF2`": Draw a surface plot using colors to show the cell
-    contents
-
--   "`SURF3`": Same as `SURF` with a contour view on the top
-
--   "`SURF4`": Draw a surface plot using `Gouraud` shading
-
--   "`SURF5`": Same as `SURF3` but only the colored contour is drawn.
-    Used with options `CYL` , `SPH` or `PSR` it allows to draw colored
-    contours on a sphere, a cylinder or in a pseudo rapidly space. In
-    Cartesian or polar coordinates, option `SURF3` is used.
-
-#### The BAR Options
-
-When the option "`bar`" or "`hbar`" is specified, a bar chart is
-drawn.
-
-The options for vertical bar chart are "`bar`", "`bar0`", "`
-bar1`", "`bar2`", "`bar3`", "`bar4`".
-
-![Vertical bar charts](pictures/02000036.png)
-
--   The bar is filled with the histogram fill color.
--   The left side of the bar is drawn with a light fill color.
--   The right side of the bar is drawn with a dark fill color.
--   The percentage of the bar drawn with either the light or dark
-    color is:
-    -   0 per cent for option `"bar"` or `"bar0"`
-    -   10 per cent for option `"bar1"`
-    -   20 per cent for option `"bar2"`
-    -   30 per cent for option `"bar3"`
-    -   40 per cent for option `"bar4"`
-
-Use **`TH1`**`::SetBarWidth()` to control the bar width (default is
-the bin width). Use **`TH1`**`::SetBarOffset` to control the bar
-offset (default is 0). See the example
-`$ROOTSYS/tutorials/hist/hist006_TH1_bar_charts.C`
-
-The options for the horizontal bar chart are "`hbar`", "`hbar0`",
-"`hbar1`", "`hbar2`", "`hbar3`", and "`hbar4`".
-
--   A horizontal bar is drawn for each bin.
--   The bar is filled with the histogram fill color.
--   The bottom side of the bar is drawn with a light fill color.
--   The top side of the bar is drawn with a dark fill color.
--   The percentage of the bar drawn with either the light or dark
-    color is:
-    -   0 per cent for option "`hbar`" or "`hbar0`"
-    -   10 per cent for option "`hbar1`"
-    -   20 per cent for option "`hbar2`"
-    -   30 per cent for option "`hbar3`"
-    -   40 per cent for option "`hbar4`"
-
-Use **`TH1`**`::SetBarWidth` to control the bar width (default is the
-bin width). Use **`TH1`**`::SetBarOffset` to control the bar offset
-(default is 0). See the example `$ROOTSYS/tutorials/hist/hist006_TH1_bar_charts.C`
-
-![Horizontal bar charts](pictures/02000037.png)
-
-#### The Z Option: Display the Color Palette on the Pad
-
-The "`Z`" option can be specified with the options: `COL`, `CONT`,
-`SURF`, and `LEGO` to display the color palette with an axis
-indicating the value of the corresponding color on the right side of
-the picture. If there is not enough space on the right side, you can
-increase the size of the right margin by calling
-**`TPad`**`::SetRightMargin()`. The attributes used to display the
-palette axis values are taken from the Z axis of the object. For
-example, you can set the labels size on the palette axis with:
-
-``` {.cpp}
-   hist->GetZaxis()->SetLabelSize();
-```
-
-#### Setting the Color Palette
-
-You can set the color palette with **`TStyle`**`::SetPalette` , e.g.
-
-``` {.cpp}
-   gStyle->SetPalette(ncolors,colors);
-```
-
-For example, the option `COL` draws a 2-D histogram with cells
-represented by a box filled with a color index, which is a function of
-the cell content. If the cell content is N, the color index used will
-be the color number in `colors[N]` . If the maximum cell content is
-greater than `ncolors` , all cell contents are scaled to `ncolors`. If
-`ncolors<=0`, a default palette of 50 colors is defined. This palette
-is recommended for pads, labels. It defines:
-
--   Index 0 to 9: shades of gray
--   Index 10 to 19:shades of brown
--   Index 20 to 29:shades of blue
--   Index 30 to 39: shades of red
--   Index 40 to 49:basic colors
-
-The color numbers specified in this palette can be viewed by selecting
-the menu entry Colors in the View menu of the canvas menu bar. The
-color's red, green, and blue values can be changed via
-**`TColor`**`::SetRGB`.
-
-If `ncolors == 1 && colors == 0`, then a Pretty Palette with a
-spectrum violet to red is created with 50 colors. That's the default
-rain bow palette.
-
-Other predefined palettes with 255 colors are available when
-`colors == 0`. The following value of `ncolors` (with `colors = 0`)
-give access to:
-
-- `ncolors = 51` : Deep Sea palette.
-- `ncolors = 52` : Grey Scale palette.
-- `ncolors = 53` : Dark Body Radiator palette.
-- `ncolors = 54` : Two-color hue palette palette. (dark blue through
-   neutral gray to bright yellow)
-- `ncolors = 55` : Rain Bow palette.
-- `ncolors = 56` : Inverted Dark Body Radiator palette.
-
-The color numbers specified in the palette can be viewed by selecting
-the item "colors" in the "VIEW" menu of the canvas toolbar.
-The color parameters can be changed via `TColor::SetRGB`.
-
-Note that when drawing a 2D histogram `h2` with the option "`COL`" or
-"`COLZ`" or with any "`CONT`" options using the color map, the number
-of colors used is defined by the number of contours `n` specified
-with: `h2->SetContour(n)`
-
-#### TPaletteAxis
-
-A **`TPaletteAxis`**object is used to display
-the color palette when drawing 2D histograms. The object is
-automatically created when drawing a 2D histogram when the option
-"`z`" is specified. It is added to the histogram list of functions.
-It can be retrieved and its attributes can be changed with:
-
-``` {.cpp}
-   TPaletteAxis *palette=(TPaletteAxis*)h->FindObject("palette");
-```
-
-The palette can be interactively moved and resized. The context menu
-can be used to set the axis attributes. It is possible to select a
-range on the axis, to set the min/max in z.
-
-#### The SPEC Option
-
-The "SPEC" option offers a large set of options/attributes to
-visualize 2D histograms thanks to "operators" following the "SPEC"
-keyword. For example, to draw the 2-D histogram `h2` using all default
-attributes except the viewing angles, one can do:
-
-``` {.cpp}
-   h2->Draw("SPEC a(30,30,0)");
-```
-
-The operators' names are case insensitive (i.e. one can use "a" or
-"A") and their parameters are separated by coma ",". Operators can be
-put in any order in the option and must be separated by a space " ".
-No space characters should be put in an operator. All the available
-operators are described below.
-
-The way how a 2D histogram will be painted is controlled by two
-parameters: the "Display modes groups" and the "Display Modes".
-"Display modes groups" can take the following values:
-
--   0 = Simple - simple display modes using one color only
--   1 = Light - the shading is carried out according to the position
-    of the fictive light source
--   2 = Height - the shading is carried out according to the channel
-    contents
--   3 = LightHeight - combination of two previous shading algorithms
-    (one can control the weight between both algorithms).
-
-"Display modes" can take the following values:
-
-- 1 = Points
-- 2 = Grid
-- 3 = Contours
-- 4 = Bars
-- 5 = LinesX
-- 6 = LinesY
-- 7 = BarsX
-- 8 = BarsY
-- 9 = Needles
-- 10 = Surface
-- 11 = Triangles
-
-These parameters can be set by using the "`dm`" operator in the
-option.
-
-``` {.cpp}
-   h2->Draw("SPEC dm(1,2)");
-```
-
-The above example draws the histogram using the "Light Display mode
-group" and the "Grid Display mode". The following tables summarize all
-the possible combinations of both groups:
-
-+-----------+------+----+--------+----+------+------+
-|           |Points|Grid|Contours|Bars|LinesX|LinesY|
-+-----------+------+----+--------+----+------+------+
-|Simple     | x    | x  | x      |x   |x     |x     |
-+-----------+------+----+--------+----+------+------+
-|Light      | x    | x  | -      |-   |x     |x     |
-+-----------+------+----+--------+----+------+------+
-|Height     | x    | x  | x      |x   |x     |x     |
-+-----------+------+----+--------+----+------+------+
-|LightHeight| x    | x  | -      |-   |x     |x     |
-+-----------+------+----+--------+----+------+------+
-
-
-+------------+-----+-----+-------+-------+----------+
-|            |BarsX|BarsY|Needles|Surface|Triangles |
-+------------+-----+-----+-------+-------+----------+
-|Simple      |x    |x    |x      |-      |x         |
-+------------+-----+-----+-------+-------+----------+
-|Light       |-    |-    |-      |x      |x         |
-+------------+-----+-----+-------+-------+----------+
-|Height      |x    |x    |-      |x      |x         |
-+------------+-----+-----+-------+-------+----------+
-|LightHeight |-    |-    |-      |x      |x         |
-+------------+-----+-----+-------+-------+----------+
-
-The "Pen Attributes" can be changed using `pa(color,style,width)`.
-Next example sets line color to 2, line type to 1 and line width to 2.
-Note that if `pa()` is not specified, the histogram line attributes
-are used:
-
-``` {.cpp}
-   h2->Draw("SPEC dm(1,2) pa(2,1,2)");
-```
-
-The number of "Nodes" can be changed with `n(nodesx,nodesy)`. Example:
-
-``` {.cpp}
-   h2->Draw("SPEC n(40,40)");
-```
-
-Sometimes the displayed region is rather large. When displaying all
-channels the pictures become very dense and complicated. It is very
-difficult to understand the overall shape of data. "`n(nx,ny)`" allows
-to change the density of displayed channels. Only the channels
-coinciding with given nodes are displayed.
-
-The visualization "Angles" can be changed with "`a(alpha,beta,view)`":
-"`alpha`" is the angle between the bottom horizontal screen line and
-the displayed space on the right side of the picture and "`beta`" on
-the left side, respectively. One can rotate the 3-d space around the
-vertical axis using the "`view`" parameter. Allowed values are 0, 90,
-180 and 270 degrees.
-
-``` {.cpp}
-   h2->Draw("SPEC n(40,40) dm(0,1) a(30,30,0)");
-```
-
-The operator "`zs(scale)`" changes the scale of the Z-axis. The
-possible values are:
-
-- 0 = Linear (default),
-- 1 = Log,
-- 2 = Sqrt.
-
-If `gPad->SetLogz()` has been set, the log scale on Z-axis is set
-automatically, i.e. there is no need for using the `zs()` operator.
-Note that the X and Y axis are always linear.
-
-The operator "`ci(r,g,b`)" defines the colors increments (`r`, `g`
-and `b` are floats). For sophisticated shading (Light, Height and
-LightHeight Display Modes Groups) the color palette starts from the
-basic pen color (see `pa()` function). There is a predefined number of
-color levels (256). Color in every level is calculated by adding the
-increments of the `r` , `g` , `b` components to the previous level.
-Using this function one can change the color increments between two
-neighboring color levels. The function does not apply on the Simple
-Display Modes Group. The default values are: (1,1,1).
-
-The operator "`ca(color_algorithm)`" allows to choose the Color
-Algorithm. To define the colors one can use one of the following color
-algorithms (RGB, CMY, CIE, YIQ, HVS models). When the level of a
-component reaches the limit value one can choose either smooth
-transition (by decreasing the limit value) or a sharp modulo
-transition (continuing with 0 value). This allows various visual
-effects. One can choose from the following set of the algorithms:
-
-- 0 = RGB Smooth,
-- 1 = RGB Modulo,
-- 2 = CMY Smooth,
-- 3 = CMY Modulo,
-- 4 = CIE Smooth
-- 5 = CIE Modulo,
-- 6 = YIQ Smooth,
-- 7 = YIQ Modulo,
-- 8 = HVS Smooth,
-- 9 = HVS Modulo
-
-This function does not apply on Simple display modes group. Default
-value is 0. Example choosing CMY Modulo to paint the 2D histogram:
-
-``` {.cpp}
-   h2->Draw("SPEC c1(3) dm(0,1) a(30,30,0)");
-```
-
-The operator "`lp(x,y,z)`" sets the light position. In Light and
-LightHeight display modes groups the color palette is calculated
-according to the fictive light source position in 3-d space. Using
-this function one can change the source's position and thus achieve
-various graphical effects. This function does not apply for Simple and
-Height display modes groups. Default is: `lp(1000,1000,100)` .
-
-The operator "`s(shading,shadow)`" allows to set the shading. The
-surface picture is composed of triangles. The edges of the neighboring
-triangles can be smoothed (shaded). The shadow can be painted as well.
-The function does not apply on Simple display modes group. The
-possible values for shading are:
-
-- 0 = Not Shaded,
-- 1 = Shaded.
-
-The possible values for shadow are:
-
-- 0 = Shadows are not painted,
-- 1 = Shadows are painted.
-
-Default values: `s(1,0)` .
-
-The operator "`b(bezier)`" sets the Bezier smoothing. For Simple
-display modes group and for Grid, LinesX and LinesY display modes one
-can smooth data using Bezier smoothing algorithm. The function does
-not apply on other display modes groups and display modes. Possible
-values are: 0 = No bezier smoothing, 1 = Bezier smoothing. Default
-value is: `b(0)`.
-
-The operator "`cw(width)`" sets the contour width. This function
-applies only on for the Contours display mode. One can change the
-width between horizontal slices and thus their density. Default value:
-`cw(50)` .
-
-The operator "`lhw(weight)`" sets the light height weight. For
-LightHeight display modes group one can change the weight between both
-shading algorithms. The function does not apply on other display modes
-groups. Default value is `lhw(0.5)` .
-
-The operator "`cm(enable,color,width,height,style)`" allows to
-draw a marker on each node. In addition to the surface drawn using any
-above given algorithm one can display channel marks. One can control
-the color as well as the width, height (in pixels) and the style of
-the marks. The parameter `enable` can be set to 0 = Channel marks are
-not drawn or 1 = Channel marks drawn. The possible styles are:
-
-- 1 = Dot,
-- 2 = Cross,
-- 3 = Star,
-- 4 = Rectangle,
-- 5 = X,
-- 6 = Diamond,
-- 7 = Triangle.
-
-The operator "`cg(enable,color)`" channel grid. In addition to the
-surface drawn using any above given algorithm one can display grid
-using the color parameter. The parameter enable can be set to:
-
-- 0 = Grid not drawn,
-- 1 = Grid drawn.
-
-See the example in `$ROOTSYS/tutorials/spectrum/spectrumpainter.C` .
-
-![The picture produced by spectrumpainter.C macro](pictures/03000038.png)
-
-#### 3-D Histograms
-
-By default a 3D scatter plot is drawn. If the "BOX" option is
-specified, a 3D box with a volume proportional to the cell content is
-drawn.
-
-### Drawing a Sub-range of a 2-D Histogram
-
-
-![The picture produced by fit2a.C macro](pictures/02000039.png)
-
-Using a **`TCutG`** object, it is possible to draw a 2D
-histogram sub-range. One must create a graphical cut (mouse or C++)
-and specify the name of the cut between "`[`" and "`]`" in the Draw
-option.
-
-For example, with a **`TCutG`**named "`cutg`", one can call:
-
-``` {.cpp}
-   myhist->Draw("surf1 [cutg]");
-```
-
-Or, assuming two graphical cuts with name "`cut1`" and "`cut2`", one
-can do:
-
-``` {.cpp}
-   h1.Draw("lego");
-   h2.Draw("[cut1,-cut2],surf,same");
-```
-
-The second `Draw` will superimpose on top of the first lego plot a
-subset of `h2`using the "`surf`" option with:
-
--   all the bins inside `cut1`
--   all the bins outside `cut2`
-
-Up to 16 cuts may be specified in the cut string delimited by
-`"[..]"`. Currently only the following drawing options are sensitive
-to the cuts option: `col` , `box` , `scat` , `hist` , `lego` , `surf`
-and `cartesian` coordinates only. See a complete example in the
-tutorial `$ROOTSYS/tutorials/fit/fit2a.C` .
-
-### Superimposing Histograms with Different Scales
-
-
-The following script creates two histograms; the second histogram is
-the bins integral of the first one. It shows a procedure to draw the
-two histograms in the same pad and it draws the scale of the second
-histogram using a new vertical axis on the right side.
-
-![Superimposed histograms with different scales](pictures/0300003A.png)
-
-``` {.cpp}
-void twoscales() {
-   TCanvas *c1 = new TCanvas("c1","different scales hists",600,400);
-   //create, fill and draw h1
-   gStyle->SetOptStat(kFALSE);
-   TH1F *h1 = new TH1F("h1","my histogram",100,-3,3);
-   for (Int_t i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
-   h1->Draw();
-   c1->Update();
-   //create hint1 filled with the bins integral of h1
-   TH1F *hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
-   Float_t sum = 0;
-   for (Int_t i=1;i<=100;i++) {
-      sum += h1->GetBinContent(i);
-      hint1->SetBinContent(i,sum);
-   }
-   //scale hint1 to the pad coordinates
-   Float_t rightmax = 1.1*hint1->GetMaximum();
-   Float_t scale    = gPad->GetUymax()/rightmax;
-   hint1->SetLineColor(kRed);
-   hint1->Scale(scale);
-   hint1->Draw("same");
-   //draw an axis on the right side
-   TGaxis*axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
-                            gPad->GetUxmax(),gPad->GetUymax(),
-                            0,rightmax,510,"+L");
-   axis->SetLineColor(kRed);
-   axis->SetLabelColor(kRed);
-   axis->Draw();
-}
-```
-
-### Statistics Display
-
-
-By default, a histogram drawing includes the statistics box. Use
-**`TH1`**`::SetStats(kFALSE)` to eliminate the statistics box. If the
-statistics box is drawn, `gStyle->SetOptStat(mode)` allow you to
-select the type of displayed information `.` The parameter `mode` has
-up to nine digits that can be set OFF (0) or ON as follows:
-
-`mode = ksiourmen` (`default =000001111`)
-
--   `n` = 1 the name of histogram is printed
--   `e` = 1 the number of entries
--   `m` = 1 the mean value
--   `m` = 2 the mean and mean error values
--   `r` = 1 the root mean square (RMS)
--   `r` = 2 the RMS and RMS error
--   `u` = 1 the number of underflows
--   `o` = 1 the number of overflows
--   `i` = 1 the integral of bins
--   `s` = 1 the skewness
--   `s` = 2 the skewness and the skewness error
--   `k` = 1 the kurtosis
--   `k` = 2 the kurtosis and the kurtosis error
-
-Never call `SetOptStat(0001111)` , but `SetOptStat(1111)` , because
-`0001111` will be taken as an octal number.
-
-The method **`TStyle`**`::SetOptStat(Option_t*option)` can also be
-called with a character string as a parameter. The parameter `option`
-can contain:
-
--   `n` for printing the name of histogram
--   `e` the number of entries
--   `m` the mean value
--   `M` the mean and mean error values
--   `r` the root mean square (RMS)
--   `R` the RMS and RMS error
--   `u` the number of underflows
--   `o` the number of overflows
--   `i` the integral of bins
--   `s` the skewness
--   `S` the skewness and the skewness error
--   `k` the kurtosis
--   `K` the kurtosis and the kurtosis error
-
-``` {.cpp}
-   gStyle->SetOptStat("ne");   // prints the histogram name and number
-                               // of entries
-   gStyle->SetOptStat("n");    // prints the histogram name
-   gStyle->SetOptStat("nemr"); // the default value
-```
-
-With the option `"same"`, the statistic box is not redrawn. With the
-option `"sames"`, it is re-drawn. If it hides the previous statistics
-box, you can change its position with the next lines (where `h` is the
-histogram pointer):
-
-``` {.cpp}
-root[] TPaveStats *s =
-            (TPaveStats*)h->GetListOfFunctions()->FindObject("stats");
-root[] s->SetX1NDC (newx1); // new x start position
-root[] s->SetX2NDC (newx2); // new x end position
-```
-
-### Setting Line, Fill, Marker, and Text Attributes
-
-
-The histogram classes inherit from the attribute classes:
-**`TAttLine`**, **`TAttFill`**, **`TAttMarker`** and **`TAttText`**.
-See the description of these classes for the list of options.
-
-### Setting Tick Marks on the Axis
-
-
-The **`TPad`**`::SetTicks()` method specifies the type of tick
-marks on the axis. Let `tx=gPad->GetTickx()` and
-`ty=gPad->GetTicky()`.
-
--   `tx` = 1; tick marks on top side are drawn (inside)
--   `tx` = 2; tick marks and labels on top side are drawn
--   `ty` = 1; tick marks on right side are drawn (inside)
--   `ty` = 2; tick marks and labels on right side are drawn
--   `tx=ty=0` by default only the left Y axis and X bottom axis are
-     drawn
-
-Use **`TPad`**`::SetTicks(tx,ty)` to set these options. See also
-the methods of **`TAxis`** that set specific axis attributes. If
-multiple color-filled histograms are drawn on the same pad, the fill
-area may hide the axis tick marks. One can force the axis redrawing
-over all the histograms by calling:
-
-``` {.cpp}
-   gPad->RedrawAxis();
-```
-
-### Giving Titles to the X, Y and Z Axis
-
-
-Because the axis title is an attribute of the axis, you have to get
-the axis first and then call **`TAxis`**`::SetTitle`.
-
-``` {.cpp}
-   h->GetXaxis()->SetTitle("X axis title");
-   h->GetYaxis()->SetTitle("Y axis title");
-   h->GetZaxis()->SetTitle("Z axis title");
-```
-
-The histogram title and the axis titles can be any **`TLatex`**
-string. The titles are part of the persistent histogram. For example
-if you wanted to write E with a subscript (T) you could use this:
-
-``` {.cpp}
-   h->GetXaxis()->SetTitle("E_{T}");
-```
-
-For a complete explanation of the Latex mathematical expressions, see
-"Graphics and the Graphical User Interface". It is also possible to
-specify the histogram title and the axis titles at creation time.
-These titles can be given in the "title" parameter. They must be
-separated by "**;**":
-
-``` {.cpp}
-   TH1F* h=new TH1F("h","Histogram title;X Axis;Y Axis;Z Axis",
-                    100,0,1);
-```
-
-Any title can be omitted:
-
-``` {.cpp}
-   TH1F* h=new TH1F("h","Histogram title;;Y Axis",100,0,1);
-   TH1F* h=new TH1F("h",";;Y Axis",100,0,1);
-```
-
-The method `SetTitle` has the same syntax:
-
-``` {.cpp}
-   h->SetTitle("Histogram title;An other X title Axis");
-```
-
-## Making a Copy of an Histogram
-
-
-Like for any other ROOT object derived from **`TObject`** , the
-`Clone` method can be used. This makes an identical copy of the
-original histogram including all associated errors and functions:
-
-``` {.cpp}
-   TH1F *hnew = (TH1F*)h->Clone(); // renaming is recommended,
-   hnew->SetName("hnew");          // because otherwise you will have
-                                   // two histograms with the same
-                                   // name
-```
-
-## Normalizing Histograms
-
-
-You can scale a histogram ( **`TH1`** `*h` ) such that the bins
-integral is equal to the normalization parameter norm:
-
-``` {.cpp}
-   Double_t scale = norm/h->Integral();
-   h->Scale(scale);
-```
-
-## Saving/Reading Histograms to/from a File
-
-
-The following statements create a ROOT file and store a histogram on
-the file. Because **`TH1`** derives from **`TNamed`** , the key
-identifier on the file is the histogram name:
-
-``` {.cpp}
-   TFile f("histos.root","new");
-   TH1F h1("hgaus","histo from a gaussian",100,-3,3);
-   h1.FillRandom("gaus",10000);
-   h1->Write();
-```
-
-To read this histogram in another ROOT session, do:
-
-``` {.cpp}
-   TFile f("histos.root");
-   TH1F *h = (TH1F*)f.Get("hgaus");
-```
-
-One can save all histograms in memory to the file by:
-
-``` {.cpp}
-   file->Write();
-```
-
-For a more detailed explanation, see "Input/Output".
-
-## Miscellaneous Operations
-
-
--   **`TH1`**`::KolmogorovTest(` **`TH1`**`* h2,Option_t *option)` is
-    statistical test of compatibility in shape between two histograms.
-    The parameter `option` is a character string that specifies:
-
--   "`U`" include Underflows in test (also for 2-dim)
-
--   "`O`" include Overflows (also valid for 2-dim)
-
--   "`N`" include comparison of normalizations
-
--   "`D`" put out a line of "Debug" printout
-
--   "`M`" return the maximum Kolmogorov distance instead of `prob`
-
--   "`X`" run the pseudo experiments post-processor with the following
-    procedure: it makes pseudo experiments based on random values from
-    the parent distribution and compare the KS distance of the pseudo
-    experiment to the parent distribution. Bin the KS distances in a
-    histogram, and then take the integral of all the KS values above
-    the value obtained from the original data to Monte Carlo
-    distribution. The number of pseudo-experiments NEXPT is currently
-    fixed at 1000. The function returns the integral. Note that this
-    option "`X`" is much slower.
-
--   **`TH1`**`::Smooth` - smoothes the bin contents of a 1D histogram.
-
--   **`TH1`**`::Integral(Option_t *opt)-`returns the integral of bin
-    contents in a given bin range. If the option "`width`" is
-    specified, the integral is the sum of the bin contents multiplied
-    by the bin width in `x` .
-
--   **`TH1`**`::GetMean(int axis)` - returns the mean value along axis.
-
--   **`TH1`**`::GetStdDev(int axis)` - returns the sigma distribution along axis.
-
--   **`TH1`**`::GetRMS(int axis)` - returns the Root Mean Square
-    along axis.
-
--   **`TH1`**`::GetEntries()` - returns the number of entries.
-
--   **`TH1`**`::GetAsymmetry(`**`TH1`** `*h2,Double_t c2,Double_tdc2)`
-    - returns an histogram containing the asymmetry of this histogram
-    with `h2`, where the asymmetry is defined as:
-
-``` {.cpp}
-   Asymmetry = (h1 - h2)/(h1 + h2); //where h1 = this
-```
-
--   It works for `1D` , `2D` , etc. histograms. The parameter `c2` is
-    an optional argument that gives a relative weight between the two
-    histograms, and `dc` `2` is the error on this weight. This is
-    useful, for example, when forming an asymmetry between two
-    histograms from two different data sets that need to be normalized
-    to each other in some way. The function calculates the errors
-    assuming Poisson statistics on `h1` and `h2`
-    (that is, `dh=sqrt(h)`). In the next example we assume that `h1`
-    and `h2` are already filled:
-
-``` {.cpp}
-   h3 = h1->GetAsymmetry(h2);
-```
-
--   Then `h3` is created and filled with the asymmetry between `h1`
-    and `h2` ; `h1` and `h2` are left intact.
-
--   Note that the user's responsibility is to manage the created
-    histograms.
-
--   **`TH1`**`::Reset()` - resets the bin contents and errors of a
-    histogram
-
-## Important note on returned statistics (`GetMean`, `GetStdDev`, etc.)
-
-
-By default, histogram statistics are computed at fill time using the
-unbinned data used to update the bin content. **This means the values
-returned by `GetMean`, `GetStdDev`, etc., are those of the dataset used
-to fill the histogram**, not those of the binned content of the histogram
-itself, **unless one of the axes has been zoomed**. (See the documentation
-on `TH1::GetStats()`.) This is useful if you want to keep track of the
-mean and standard deviation of the dataset you are visualizing with the histogram,
-but it can lead to some unintuitive results.
-
-For example, suppose you have a histogram
-with one bin between 0 and 100, then you fill it with a
-Gaussian dataset with mean 20 and standard deviation 2:
-``` {.cpp}
-TH1F * h = new TH1F("h", "h", 1, 0, 100);
-for(int i=0; i<10000; i++) h->Fill(gRandom->Gaus(20, 2));
-```
-Right now, `h->GetMean()` will return 20 and `h->GetStdDev()` will return 2;
-ROOT calculated these values as we filled `h`.
-Next, zoom in on the Gaussian:
-``` {.cpp}
-h->GetXaxis()->SetRangeUser(10, 30);
-```
-Now, `h->GetMean()` will return 50 and `h->GetStdDev()` will return 0.
-What happened? Well, `GetMean` and `GetStdDev` (and many other `TH1` functions)
-return the statistics for *bins in range*; this is because the histogram only
-stores the contents of its bins, not the coordinates of the values used to fill it.
-So even though `h` has only one bin and it's still included in the range, ROOT returns the
-binned statistics because `SetRangeUser` set the bit `TAxis::kAxisRange` to 1.
-*This remains true even if you zoom out:*
-``` {.cpp}
-h->GetXaxis()->SetRangeUser(0, 100);
-```
-still results in `GetMean` and `GetStdDev` returning 50 and 0, respectively,
-because, even though this is the original range of the histogram, *the X axis has
-still been assigned a range*. To mark the X axis as having no range, you can call
-``` {.cpp}
-h->GetXaxis()->SetRange();
-```
-without arguments or with arguments `(0, 0)`. This sets the bit `TAxis::kAxisRange` to 0,
-and ROOT again uses the statistics calculated at fill time: `GetMean` and `GetStdDev`
-now return 20 and 2, respectively.
-
-If you want ROOT to consistently return the statistics of the binned dataset stored
-in the histogram and not those of the dataset used to fill it, you can call
-`TH1::ResetStats`. This will delete the statistics originally calculated at fill
-time and replace them with those calculated from the bins; note that you cannot later
-retrieve the original statistics--they are lost. Continuing the example above,
-``` {.cpp}
-h->ResetStats();
-h->GetXaxis()->SetRange();
-```
-results in `GetMean` and `GetStdDev` returning 50 and 0, respectively.
-If you fill the histogram again, the statistics will be a mix of binned and
-unbinned:
-``` {.cpp}
-h->ResetStats();
-h->GetXaxis()->SetRange();
-for(int i=0; i<10000; i++) h->Fill(85);
-```
-results in `GetMean` and `GetStdDev` returning 67.5 and 17.5, respectively;
-you must call `TH1::ResetStats` again to get consistent binned statistics.
-
-
-## Alphanumeric Bin Labels
-
-
-By default, a histogram axis is drawn with its numeric bin labels. One
-can specify alphanumeric labels instead.
-
-### Option 1: SetBinLabel
-
-
-To set an alphanumeric bin label call:
-
-``` {.cpp}
-   TAxis::SetBinLabel(bin,label);
-```
-
-This can always be done before or after filling. Bin labels will be
-automatically drawn with the histogram.
-
-![Histograms with alphanumeric bin labels](pictures/0600003B.png)
-
-See example in `$ROOTSYS/tutorials/hist/hlabels1.C` , `hlabels2.C`
-
-### Option 2: Fill
-
-
-You can also call a `Fill()` function with one of the arguments being
-a string:
-
-``` {.cpp}
-   hist1->Fill(somename,weigth);
-   hist2->Fill(x,somename,weight);
-   hist2->Fill(somename,y,weight);
-   hist2->Fill(somenamex,somenamey,weight);
-```
-
-### Option 3: TTree::Draw
-
-
-You can use a char\* variable type to histogram strings with
-**`TTree`**`::Draw()`.
-
-``` {.cpp}
-   // here "Nation" and "Division" are two char* branches of a Tree
-   tree.Draw("Nation::Division", "", "text");
-```
-
-![Using a \*char variable type in TTree::Draw](pictures/0200003C.png)
-
-There is an example in `$ROOTSYS/tutorials/io/tree/tree502_cernstaff.C.`
-
-If a variable is defined as `char*` it is drawn as a string by default.
-You change that and draw the value of `char[0]` as an integer by
-adding an arithmetic operation to the expression as shown below.
-
-``` {.cpp}
-   // draw the integer value of MyChar[0] where "MyChar" is char[5]
-   tree.Draw("MyChar + 0");
-```
-
-### Sort Options
-
-
-When using the options 2 or 3 above, the labels are automatically
-added to the list (**`THashList`**) of labels for a given axis. By
-default, an axis is drawn with the order of bins corresponding to the
-filling sequence. It is possible to reorder the axis alphabetically or
-by increasing or decreasing values. The reordering can be triggered
-via the **`TAxis`** context menu by selecting the menu item
-"`LabelsOption` " or by calling directly.
-
-``` {.cpp}
-   TH1::LabelsOption(option,axis);
-```
-
-Here `axis` may be X, Y, or Z. The parameter `option` may be:
-
--   "`a`" sort by alphabetic order
--   "`>`" sort by decreasing values
--   "`<`" sort by increasing values
--   "`h`" draw labels horizontal
--   "`v`" draw labels vertical
--   "`u`" draw labels up (end of label right adjusted)
--   "`d`" draw labels down (start of label left adjusted)
-
-When using the option second above, new labels are added by doubling
-the current number of bins in case one label does not exist yet. When
-the filling is terminated, it is possible to trim the number of bins
-to match the number of active labels by calling:
-
-``` {.cpp}
-   TH1::LabelsDeflate(axis);
-```
-
-Here `axis` may be X, Y, or Z. This operation is automatic when using
-**`TTree`**`::Draw` . Once bin labels have been created, they become
-persistent if the histogram is written to a file or when generating
-the C++ code via `SavePrimitive` .
-
-## Histogram Stacks
-
-
-A **`THStack`** is a collection of **`TH1`** (or derived) objects. Use
-**`THStack`**`::Add(` **`TH1`** `*h)` to add a histogram to the stack.
-The **`THStack`** does not own the objects in the list.
-
-![Stacked histograms](pictures/0300003D.png)
-
-By default, **`THStack`**`::Draw` draws the histograms stacked as
-shown in the left pad in the picture above. If the option `"nostack"`
-is used, the histograms are superimposed as if they were drawn one at
-a time using the `"same"` draw option `.` The right pad in this
-picture illustrates the **`THStack`** drawn with the `"nostack"`
-option.
-
-``` {.cpp}
-   hs->Draw("nostack");
-```
-
-Next is a simple example, for a more complex one see
-`$ROOTSYS/tutorials/hist/hstack.C.`
-
-``` {.cpp}
-{
-   THStack hs("hs","test stacked histograms");
-   TH1F *h1 = new TH1F("h1","test hstack",100,-4,4);
-   h1->FillRandom("gaus",20000);
-   h1->SetFillColor(kRed);
-   hs.Add(h1);
-   TH1F *h2 = new TH1F("h2","test hstack",100,-4,4);
-   h2->FillRandom("gaus",15000);
-   h2->SetFillColor(kBlue);
-   hs.Add(h2);
-   TH1F *h3 = new TH1F("h3","test hstack",100,-4,4);
-   h3->FillRandom("gaus",10000);
-   h3->SetFillColor(kGreen);
-   hs.Add(h3);
-   TCanvas c1("c1","stacked hists",10,10,700,900);
-   c1.Divide (1,2);
-   c1.cd(1);
-   hs.Draw();
-   c1.cd(2);
-   hs->Draw("nostack");
-}
-```
-
-## TH2Poly
-
-
-`TH2Poly` is a 2D Histogram class allowing to define polygonal bins of
-arbitrary shape.
-
-Each bin in the `TH2Poly` histogram is a `TH2PolyBin` object.
-`TH2PolyBin` is a very simple class containing the vertices and
-contents of the polygonal bin as well as several related functions.
-
-Bins are defined using one of the `AddBin()` methods. The bin
-definition should be done before filling.
-
-The following very simple macro shows how to build and fill a
-`TH2Poly`:
-
-``` {.cpp}
-{
-   TH2Poly *h2p = new TH2Poly();
-   Double_t x1[] = {0, 5, 5};
-   Double_t y1[] = {0, 0, 5};
-   Double_t x2[] = {0, -1, -1, 0};
-   Double_t y2[] = {0, 0, -1, -1};
-   Double_t x3[] = {4, 3, 0, 1, 2.4};
-   Double_t y3[] = {4, 3.7, 1, 4.7, 3.5};
-   h2p->AddBin(3, x1, y1);
-   h2p->AddBin(3, x2, y2);
-   h2p->AddBin(3, x3, y3);
-   h2p->Fill( 3, 1, 3);      // fill bin 1
-   h2p->Fill(-0.5, -0.5, 7); // fill bin 2
-   h2p->Fill(-0.7, -0.5, 1); // fill bin 2
-   h2p->Fill( 1, 3, 5);      // fill bin 3
-}
-```
-
-More examples can bin found in `$ROOTSYS/tutorials/hist/th2poly*.C`
-
-![A TH2Poly histogram example](pictures/th2poly1.png)
-
-## Profile Histograms
-
-
-Profile histograms are in many cases an elegant replacement of
-two-dimensional histograms. The relationship of two quantities X and Y
-can be visualized by a two-dimensional histogram or a scatter-plot;
-its representation is not particularly satisfactory, except for sparse
-data. If Y is an unknown [but single-valued] function of X, it can be
-displayed by a profile histogram with much better precision than by a
-scatter-plot. Profile histograms display the mean value of Y and its
-RMS for each bin in X. The following shows the contents
-[capital letters] and the values shown in the graphics [small letters]
-of the elements for bin j. When you fill a profile histogram with
-**`TProfile`**`.Fill(x,y)` :
-
--   `H[j]` will contain for each bin `j` the sum of the y values for
-    this bin
-
--   `L[j]` contains the number of entries in the bin `j`
-
--   `e[j]` or `s[j]` will be the resulting error depending on the
-    selected option. See "Build Options".
-
-``` {.cpp}
-E[j] = sum Y**2
-L[j] = number of entries in bin J
-H[j] = sum Y
-h[j] = H[j] / L[j]
-s[j] = sqrt[E[j] / L[j] - h[j]**2]
-e[j] = s[j] / sqrt[L[j]]
-```
-
-In the special case where `s[j]` is zero, when there is only one entry
-per bin, `e[j]` is computed from the average of the `s[j]` for all
-bins. This approximation is used to keep the bin during a fit
-operation. The **`TProfile`** constructor takes up to eight arguments.
-The first five parameters are similar to **`TH1D`** constructor.
-
-``` {.cpp}
-TProfile(const char *name,const char *title,Int_t nbinsx,
-         Double_t xlow, Double_t xup, Double_t ylow, Double_t yup,
-         Option_t *option)
-```
-
-All values of `y` are accepted at filling time. To fill a profile
-histogram, you must use **`TProfile`**`::Fill` function. Note that
-when filling the profile histogram the method **`TProfile`**`::Fill`
-checks if the variable `y` is between `fYmin` and `fYmax`. If a
-minimum or maximum value is set for the Y scale before filling, then
-all values below `ylow` or above `yup` will be discarded. Setting the
-minimum or maximum value for the Y scale before filling has the same
-effect as calling the special **`TProfile`** constructor above where
-`ylow` and `yup` are specified.
-
-### Build Options
-
-
-The last parameter is the build option. If a bin has N data points all
-with the same value Y, which is the case when dealing with integers,
-the spread in Y for that bin is zero, and the uncertainty assigned is
-also zero, and the bin is ignored in making subsequent fits. If
-`SQRT(Y)` was the correct error in the case above, then
-`SQRT(Y)/SQRT(N)` would be the correct error here. In fact, any bin
-with non-zero number of entries N but with zero spread
-(`spread = s[j]`) should have an uncertainty `SQRT(Y)/SQRT(N)`. Now,
-is `SQRT(Y)/SQRT(N)` really the correct uncertainty ? That it is only
-in the case where the Y variable is some sort of counting statistics,
-following a Poisson distribution. This is the default case. However, Y
-can be any variable from an original `NTUPLE`, and does not
-necessarily follow a Poisson distribution. The computation of errors
-is based on Y = values of data points; N = number of data points.
-
--   `' '` - the default is blank, the errors are:
-
--   `spread/SQRT(N)` for a non-zero spread
-
--   `SQRT(Y)/SQRT(N)` for a spread of zero and some data points
-
--   `0` for no data points
-
--   ‘ `s` ' - errors are:
-
--   `spread` for a non-zero spread
-
--   `SQRT(Y)` for a Spread of zero and some data points
-
--   `0` for no data points
-
--   ‘ `i` ' - errors are:
-
--   `spread/SQRT(N)` for a non-zero spread
-
--   `1/SQRT(12*N)` for a Spread of zero and some data points
-
--   `0` for no data points
-
--   ‘ `G` ' - errors are:
-
--   `spread/SQRT(N)` for a non-zero spread
-
--   `sigma/SQRT(N)` for a spread of zero and some data points
-
--   `0` for no data points
-
-The option ' `i` ' is used for integer Y values with the uncertainty
-of $\pm 0.5$, assuming the probability that Y takes any value between Y-0.5
-and Y+0.5 is uniform (the same argument for Y uniformly distributed
-between Y and Y+1). An example is an ADC measurement. The '`G`' option
-is useful, if all Y variables are distributed according to some known
-Gaussian of standard deviation Sigma. For example when all Y's are
-experimental quantities measured with the same instrument with
-precision Sigma. The next figure shows the graphic output of this
-simple example of a profile histogram.
-
-``` {.cpp}
-{
-   // Create a canvas giving the coordinates and the size
-   TCanvas *c1 = new TCanvas("c1", "Profile example",200,10,700,500);
-
-   // Create a profile with the name, title, the number of bins,
-   // the low and high limit of the x-axis and the low and high
-   // limit of the y-axis.
-   // No option is given so the default is used.
-   hprof = new TProfile("hprof",
-                        "Profile of pz versus px",100,-4,4,0,20);
-
-   // Fill the profile 25000 times with random numbers
-   Float_t px, py, pz;
-   for ( Int_t i=0; i<25000; i++) {
-      // Use the random number generator to get two numbers following
-      // a gaussian distribution with mean=0 and sigma=1
-      gRandom->Rannor(px,py);
-      pz = px*px + py*py;
-      hprof->Fill(px,pz,1);
-   }
-   hprof->Draw();
-}
-```
-
-![A profile histogram example](pictures/0300003E.png)
-
-### Drawing a Profile without Error Bars
-
-
-To draw a profile histogram and not show the error bars use the
-"`HIST`" option in the **`TProfile`**`::Draw` method. This will draw
-the outline of the **`TProfile`**.
-
-### Create a Profile from a 2D Histogram
-
-
-You can make a profile from a histogram using the methods
-**`TH2`**`::ProfileX` and **`TH2`**`::ProfileY`.
-
-### Create a Histogram from a Profile
-
-
-To create a regular histogram from a profile histogram, use the method
-**`TProfile`**`::ProjectionX` .This example instantiates a **`TH1D`**
-object by copying the `TH1D` piece of **`TProfile`**.
-
-``` {.cpp}
-   TH1D *sum = myProfile.ProjectionX();
-```
-
-You can do the same with a 2D profile using the method
-**`TProfile2D`**`::ProjectionXY` .
-
-### Generating a Profile from a TTree
-
-
-The `'prof'` and `'profs'` options in the **`TTree`**`::Draw` method
-generate a profile histogram ( **`TProfile`** ), given a two
-dimensional expression in the tree, or a **`TProfile2D`** given a
-three dimensional expression. See "Trees". Note that you can specify
-`'prof'` or `'profs'` : `'prof'` generates a **`TProfile`** with error
-on the mean, `'profs'` generates a **`TProfile`** with error on the
-spread.
-
-### 2D Profiles
-
-
-The class for a 2D Profile is called **`TProfile2D`** . It is in many
-cases an elegant replacement of a three-dimensional histogram. The
-relationship of three measured quantities X, Y and Z can be visualized
-by a three-dimensional histogram or scatter-plot; its representation
-is not particularly satisfactory, except for sparse data. If Z is an
-unknown (but single-valued) function of (X,Y), it can be displayed
-with a **`TProfile2D`** with better precision than by a scatter-plot.
-A **`TProfile2D`** displays the mean value of Z and its RMS for each
-cell in X, Y. The following shows the cumulated contents (capital
-letters) and the values displayed (small letters) of the elements for
-cell `i,j`.
-
-When you fill a profile histogram with **`TProfile2D`**`.Fill(x,y,z)`:
-
--   `E[i,j]` contains for each bin `i,j` the sum of the z values for
-    this bin
-
--   `L[i,j]` contains the number of entries in the bin j
-
--   `e[j]` or `s[j]` will be the resulting error depending on the
-     selected option. See "Build Options".
-
-``` {.cpp}
-E[i,j] = sum z
-L[i,j] = sum l
-h[i,j] = H[i,j ] / L[i,j]
-s[i,j] = sqrt[E[i,j] / L[i,j]- h[i,j]**2]
-e[i,j] = s[i,j] / sqrt[L[i,j]]
-```
-
-In the special case where `s[i,j]` is zero, when there is only one
-entry per cell, `e[i,j]` is computed from the average of the `s[i,j]`
-for all cells. This approximation is used to keep the cell during a
-fit operation.
-
-![A TProfile2D histogram example](pictures/0800003F.png)
-
-``` {.cpp}
-{
-   // Creating a Canvas and a TProfile2D
-   TCanvas *c1 = new TCanvas("c1",
-                             "Profile histogram example",
-                              200, 10,700,500);
-   hprof2d = new TProfile2D("hprof2d",
-                            "Profile of pz versus px and py",
-                             40,-4,4,40,-4,4,0,20);
-
-   // Filling the TProfile2D with 25000 points
-   Float_t px, py, pz;
-   for (Int_t i=0; i<25000; i++) {
-      gRandom->Rannor(px,py);
-      pz = px*px + py*py;
-      hprof2d->Fill(px,py,pz,1);
-   }
-   hprof2d->Draw();
-}
-```
-
-## Iso Surfaces
-
-
-Paint one Gouraud shaded 3d iso surface though a 3d histogram at the
-value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.
-
-``` {.cpp}
-void hist3d() {
-   TH3D *h3 = new TH3D("h3", "h3", 20, -2, 2, 20, -2, 2, 20, 0, 4);
-   Double_t x,y,z;
-   for (Int_t i=0; i<10000; i++) {
-      gRandom->
-      Rannor(x,y);
-      z=x*x+y*y;
-      h3->Fill(x,y,z);
-   }
-   h3->Draw("iso");
-}
-```
-
-![Iso surfaces](pictures/03000040.png)
-
-## 3D Implicit Functions
-
-
-``` {.cpp}
-   TF3 *fun3 = new TF3("fun3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
-   fun3->Draw();
-```
-
-![3D implicit function](pictures/03000041.png)
-
-## TPie
-
-
-The **`TPie`** class allows to create a Pie Chart representation of a
-one dimensional data set. The data can come from an array of
-`Double_t` (or `Float_t` ) or from a 1D-histogram. The possible
-options to draw a **`TPie`** are:
-
--   "`R`" Paint the labels along the central "`R`"adius of slices.
-
--   "`T`" Paint the labels in a direction "`T`"angent to circle that
-    describes the TPie.
-
--   "`3D`" Draw the pie-chart with a pseudo 3D effect.
-
--   "`NOL`" No OutLine: do not draw the slices' outlines; any property
-    over the slices' line is ignored.
-
-The method `SetLabelFormat()` is used to customize the label format.
-The format string must contain one of these modifiers:
-
--   - `%txt` : to print the text label associated with the slice
-
--   - `%val` : to print the numeric value of the slice
-
--   - `%frac` : to print the relative fraction of this slice
-
--   - `%perc` : to print the % of this slice
-
-``` {.cpp}
-   mypie->SetLabelFormat("%txt (%frac)");
-```
-
-See the macro `$ROOTSYS/tutorials/visualisation/graphics/piechart.C` .
-
-![The picture generated by tutorial macro piechart.C](pictures/03000042.png)
-
-## The User Interface for Histograms
-
-
-The classes **`T`** **`H1`** **`Editor`** and **`T`** **`H2`**
-**`Editor`** provides the user interface for setting histogram's
-attributes and rebinning interactively.
-
-### TH1Editor
-
-
-![](pictures/03000043.png)
-
-#### The Style Tab
-
-##### Title
-
-sets the title of the histogram.
-
-##### Plot
-
-draw a 2D or 3D plot; according to the dimension, different drawing
-possibilities can be set.
-
-##### Error
-add different error bars to the histogram (no errors, simple, etc.).
-
-##### Add
-further things which can be added to the histogram (None,
-simple/smooth line, fill area, etc.)
-
-#### 2-D Plot
-
-##### Simple Drawing
-draw a simple histogram without errors (= "HIST" draw
-option). In combination with some other draw options an outer line is
-drawn on top of the histogram
-
-##### Show markers
-draw a marker on to of each bin (="P" draw option).
-
-##### Draw bar chart
-draw a bar chart (="B" draw option).
-
-##### Bar option
-draw a bar chart (="BAR" draw option); if selected, it will
-show an additional interface elements for bars: width, offset,
-percentage and the possibility to draw horizontal bars.
-
-#### 3-D Plot
-
-##### Add
-set histogram type Lego-Plot or Surface draw (Lego, Lego1.2, Surf,
-Surf1...5).
-
-##### Coords
-set the coordinate system (Cartesian, Spheric, etc.).
-
-##### Error
-same as for 2D plot.
-
-##### Bar
-set the bar attributes: width and offset.
-
-##### Horizontal Bar
-draw a horizontal bar chart.
-
-#### The Binning tab
-The binning tab has two different layouts. One is for a histogram,
-which is not drawn from an ntuple. The other one is available for a
-histogram, which is drawn from an ntuple. In this case, the rebin
-algorithm can create a rebinned histogram from the original data i.e.
-the ntuple.
-
-![](pictures/03000045.png)
-
-To see the differences do:
-
-``` {.cpp}
-   TFile f("hsimple.root");
-   hpx->Draw("BAR1"); // non ntuple histogram
-   ntuple->Draw("px");// ntuple histogram
-```
-
-#### Non ntuple histogram
-
-Rebin with a slider and the number of bins (shown in the field below
-the slider). The number of bins can be changed to any number, which
-divides the number of bins of the original histogram. A click on the
-Apply button will delete the origin histogram and will replace it by
-the rebinned one on the screen. A click on the Ignore button will
-restore the origin histogram.
-
-#### Histogram drawn from an ntuple
-
-##### Rebin
-\index{histogram!rebin}
-with the slider, the number of bins can be enlarged by a factor
-of 2, 3, 4, 5 (moving to the right) or reduced by a factor of
-$\frac{1}{2}$, $\frac{1}{3}$, $\frac{1}{4}$, $\frac{1}{5}$.
-
-##### BinOffset with a BinOffset slider
-the origin of the histogram can be
-changed within one binwidth. Using this slider the effect of binning
-the data into bins can be made visible (statistical fluctuations).
-
-##### Axis Range
-with a double slider it is possible to zoom into the
-specified axis range. It is also possible to set the upper and lower
-limit in fields below the slider.
-
-##### Delayed drawing
-all the Binning sliders can set to delay draw mode.
-Then the changes on the histogram are only updated, when the Slider is
-released. This should be activated if the redrawing of the histogram
-is time consuming.
-
-### TH2Editor
-
-
-![](pictures/03000047.png)
-
-#### Style Tab:
-
-##### Title
-set the title of the histogram
-
-##### Histogram
-change the draw options of the histogram.
-
-##### Plot
-draw a 2D or 3D plot of the histogram; according to the dimension,
-the drawing possibilities are different.
-
-#### 2-D Plot
-
-##### Contour
-draw a contour plot (None, Cont0...5)
-
-##### Cont \#
-set the number of Contours;
-
-##### Arrow
-set the arrow mode and shows the gradient between adjacent cells;
-
-##### Col
-a box is drawn for each cell with a color scale varying with contents;
-
-##### Text
-draw bin contents as text;
-
-##### Box
-a box is drawn for each cell with surface proportional to contents;
-
-##### Scat
-draw a scatter-plot (default);
-
-##### Palette
-the color palette is drawn.
-
-#### 3-D Plot
-
-##### Type
-set histogram type to Lego or surface plot; draw (Lego, Lego1.2, Surf,
-Surf1...5)
-
-##### Coords
-set the coordinate system (Cartesian, Spheric, etc.);
-
-##### Cont \#
-set the number of Contours (for e.g. Lego2 draw option);
-
-##### Errors
-draw errors in a Cartesian lego plot;
-
-##### Palette
-draw the color palette;
-
-##### Front
-draw the front box of a Cartesian lego plot;
-
-##### Back
-draw the back box of a Cartesian lego plot;
-
-##### Bar
-change the bar attributes: the width and offset.
-
-#### Rebinning Tab
-
-The Rebinning tab has two different layouts. One is for a histogram
-that is not drawn from an ntuple; the other one is available for a
-histogram, which is drawn from an ntuple. In this case, the rebin
-algorithm can create a rebinned histogram from the original data i.e.
-the ntuple. To see the differences do for example:
-
-``` {.cpp}
-   TFile f ("hsimple.root");
-   hpxpy->Draw("Lego2"); // non ntuple histogram
-   ntuple->Draw("px:py","","Lego2"); // ntuple histogram
-```
-
-#### Non-ntuple histogram:
-
-Rebin with sliders (one for the x, one for the y-axis) and the number
-of bins (shown in the field below them can be changed to any number,
-which divides the number of bins of the original histogram. Selecting
-the Apply button will delete the origin histogram and will replace it
-by the rebinned one on the screen. Selecting the Ignore the origin
-histogram will be restored.
-
-![](pictures/03000049.png)
-
-#### Histogram drawn from an ntuple
-
-##### Rebin
-\index{histogram!rebin}
-with the sliders the number of bins can be enlarged by a factor of
-2,3,4,5 (moving to the right) or reduced by a factor of $\frac{1}{2}$,
-$\frac{1}{3}$, $\frac{1}{4}$, $\frac{1}{5}$.
-
-##### BinOffset
-with the BinOffset slider the origin of the histogram can
-be changed within one binwidth. Using this slider the effect of
-binning the data into bins can be made visible (=\> statistical
-fluctuations).
-
-##### Axis Range
-with a double slider that gives the possibility for
-zooming. It is also possible to set the upper and lower limit in
-fields below the slider.
-
-##### Delayed drawing
-all the binning sliders can be set to delay draw mode.
-Then the changes on the histogram are only updated, when the Slider is
-released. This should be activated if the redrawing of the histogram
-is too time consuming.
diff --git a/documentation/users-guide/InputOutput.md b/documentation/users-guide/InputOutput.md
deleted file mode 100644
index 0bbb0b511e810..0000000000000
--- a/documentation/users-guide/InputOutput.md
+++ /dev/null
@@ -1,2589 +0,0 @@
-# Input/Output
-\index{I/O}
-
-This chapter covers the saving and reading of objects to and from ROOT
-files. It begins with an explanation of the physical layout of a ROOT
-file. It includes a discussion on compression, and file recovery. Then
-we explain the logical file, the class **`TFile`** and its methods. We
-show how to navigate in a file, how to save objects and read them back.
-We also include a discussion on `Streamers`. `Streamers` are the methods
-responsible to capture an objects current state to save it to disk or
-send it over the network. At the end of the chapter is a discussion on
-the two specialized ROOT files: **`TNetFile`** and **`TWebFile`**.
-
-## The Physical Layout of ROOT Files
-
-
-A ROOT file is like a UNIX file directory. It can contain directories
-and objects organized in unlimited number of levels. It also is stored
-in machine independent format (ASCII, IEEE floating point, Big Endian
-byte ordering). To look at the physical layout of a ROOT file, we first
-create one. This example creates a ROOT file and 15 histograms, fills
-each histogram with 1000 entries from a Gaussian distribution, and
-writes them to the file.
-
-``` {.cpp}
-{
-   char name[10], title[20];
-   TObjArray Hlist(0);      // create an array of Histograms
-   TH1F* h;                 // create a pointer to a histogram
-   // make and fill 15 histograms and add them to the object array
-   for (Int_t i = 0; i < 15; i++) {
-      sprintf(name,"h%d",i);
-      sprintf(title,"histo nr:%d",i);
-      h = new TH1F(name,title,100,-4,4);
-      Hlist.Add(h);
-      h->FillRandom("gaus",1000);
-   }
-   // open a file and write the array to the file
-   TFile f("demo.root","recreate");
-   Hlist.Write();
-   f.Close();
-}
-```
-
-The example begins with a call to the **`TFile`** constructor. This
-class is describing the ROOT file (that has the extension "`.root`"). In
-the next section, we will cover **`TFile`** in details. The last line of
-the example closes the file. To view its contents we need to open it
-again, and to create a **`TBrowser`** object by:
-
-``` {.cpp}
-root[] TFile f("demo.root")
-root[] TBrowser browser;
-```
-
-![The browser with 15 created histograms](pictures/030000E6.png)
-
-You can check if the file is correctly opened by:
-
-``` {.cpp}
-   TFile f("demo.root");
-   if (f.IsZombie()) {
-      cout << "Error opening file" << endl;
-      exit(-1);
-   } else {
-      ...
-   }
-```
-
-Once we have the `TFile` object, we can call the
-**`TFile::Map()`** method to view the physical layout. The output prints
-the date/time, the start record address, the number of bytes in the
-record, the class name of the record and the compression factor.
-
-``` {.cpp}
-root[] f.Map()
-20051208/124502  At:100    N=114       TFile
-20051208/124502  At:214    N=413       TH1F           CX =  2.35
-20051208/124502  At:627    N=410       TH1F           CX =  2.36
-20051208/124502  At:1037   N=396       TH1F           CX =  2.45
-20051208/124502  At:1433   N=400       TH1F           CX =  2.42
-20051208/124502  At:1833   N=402       TH1F           CX =  2.41
-20051208/124502  At:2235   N=416       TH1F           CX =  2.33
-20051208/124502  At:2651   N=406       TH1F           CX =  2.39
-20051208/124502  At:3057   N=403       TH1F           CX =  2.40
-20051208/124502  At:3460   N=411       TH1F           CX =  2.36
-20051208/124502  At:3871   N=400       TH1F           CX =  2.42
-20051208/124502  At:4271   N=409       TH1F           CX =  2.38
-20051208/124502  At:4680   N=409       TH1F           CX =  2.38
-20051208/124502  At:5089   N=420       TH1F           CX =  2.32
-20051208/124502  At:5509   N=406       TH1F           CX =  2.40
-20051208/124502  At:5915   N=405       TH1F           CX =  2.40
-20051208/124503  At:6320   N=3052      StreamerInfo   CX =  3.16
-20051208/124503  At:9372   N=732       KeysList
-20051208/124503  At:10104  N=53        FreeSegments
-20051208/124503  At:10157  N=1         END
-```
-
-Here we see the fifteen histograms (**`TH1F`**'s) with the first one
-starting at byte 148. We also see an entry **`TFile`**. You may notice
-that the first entry starts at byte 100. The first 100 bytes are taken
-by the file header.
-
-### The File Header
-
-
-This table shows the file header information. When fVersion is greater
-than 1000000, the file is a large file (\> 2 GB) and the offsets will be
-8 bytes long. The location in brackets are the location in the case of a
-large file.
-
-+-------------------+------------------+---------------------------------------+
-| Byte              | Value Name       | Description                           |
-+-------------------+------------------+---------------------------------------+
-| 1 `->` 4          | "`root`"         | Root file identifier                  |
-+-------------------+------------------+---------------------------------------+
-| 5 `->` 8          | `fVersion`       | File format version                   |
-+-------------------+------------------+---------------------------------------+
-| 9 `->` 12         | `fBEGIN`         | Pointer to first data record          |
-+-------------------+------------------+---------------------------------------+
-| 13 `->` 16        | `fEND`           | Pointer to first free word at the EOF |
-| [13-\>20]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 17 `->` 20        | `fSeekFree`      | Pointer to FREE data record           |
-| [21-\>28]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 21 `->` 24        | `fNbytesFree`    | Number of bytes in FREE data record   |
-| [29-\>32]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 25 `->` 28        | `nfree`          | Number of free data records           |
-| [33-\>36]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 29 `->` 32        | `fNbytesName`    | Number of bytes in **`TNamed`** at    |
-| [37-\>40]         |                  | creation time                         |
-+-------------------+------------------+---------------------------------------+
-| 33 `->` 33        | `fUnits`         | Number of bytes for file pointers     |
-| [41-\>41]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 34 `->` 37        | `fCompress`      | Zip compression level                 |
-| [42-\>45]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 38 `->` 41        | `fSeekInfo`      | Pointer to **`TStreamerInfo`** record |
-| [46-\>53]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-| 42 `->` 45        | `fNBytesInfo`    | Number of bytes in                    |
-| [54-\>57]         |                  | **`TStreamerInfo`** record            |
-+-------------------+------------------+---------------------------------------+
-| 46 `->` 63        | `fCompress`      | Universal Unique ID                   |
-| [58-\>75]         |                  |                                       |
-+-------------------+------------------+---------------------------------------+
-
-The first four bytes of the file header contain the string "root" which
-identifies a file as a ROOT file. Because of this identifier, ROOT is
-not dependent on the "`.root`" extension. It is still a good idea to use
-the extension, just for us to recognize them easier. The `nfree` and
-value is the number of free records. This variable along with
-`FNBytesFree` keeps track of the free space in terms of records and
-bytes. This count also includes the deleted records, which are available
-again.
-
-### The Top Directory Description
-
-
-The 84 bytes after the file header contain the top directory
-description, including the name, the date and time it was created, and
-the date and time of the last modification.
-
-``` {.cpp}
-20010404/092347  At:64        N=84        TFile
-```
-
-### The Histogram Records
-
-
-What follows are the 15 histograms, in records of variable length.
-
-``` {.cpp}
-20010404/092347  At:148       N=380       TH1F           CX =  2.49
-20010404/092347  At:528       N=377       TH1F           CX =  2.51
-```
-
-The first 4 bytes of each record is an integer holding the number of
-bytes in this record. A negative number flags the record as deleted, and
-makes the space available for recycling in the next writing. The rest of
-bytes in the header contain all the information to identify uniquely a
-data block on the file. It is followed by the object data.
-
-The next table explains the values in each individual record. If the key
-is located past the 32 bit file limit (\> 2 GB) then some fields will be
-8 bytes instead of 4 bytes (values between the brackets):
-
-+--------------------+-------------------+--------------------------------------+
-| Byte               | Value Name        | Description                          |
-+--------------------+-------------------+--------------------------------------+
-| 1 `->` 4           | `Nbytes`          | Length of compressed object (in      |
-|                    |                   | bytes)                               |
-+--------------------+-------------------+--------------------------------------+
-| 5 `->` 6           | `Version`         | **`TKey`** version identifier        |
-+--------------------+-------------------+--------------------------------------+
-| 7 `->` 10          | `ObjLen`          | Length of uncompressed object        |
-+--------------------+-------------------+--------------------------------------+
-| 11 `->` 14         | `Datime`          | Date and time when object was        |
-|                    |                   | written to file                      |
-+--------------------+-------------------+--------------------------------------+
-| 15 `->` 16         | `KeyLen`          | Length of the key structure (in      |
-|                    |                   | bytes)                               |
-+--------------------+-------------------+--------------------------------------+
-| 17 `->` 18         | `Cycle`           | Cycle of key                         |
-+--------------------+-------------------+--------------------------------------+
-| 19 `->` 22         | `SeekKey`         | Pointer to record itself             |
-| [19-\>26]          |                   | (consistency check)                  |
-+--------------------+-------------------+--------------------------------------+
-| 23 `->` 26         | `SeekPdir`        | Pointer to directory header          |
-| [27-\>34]          |                   |                                      |
-+--------------------+-------------------+--------------------------------------+
-| 27 `->` 27         | `lname`           | Number of bytes in the class name    |
-| [35-\>35]          |                   |                                      |
-+--------------------+-------------------+--------------------------------------+
-| 28 `->` ... [36-\>...] | `ClassName`       | Object Class Name                    |
-+--------------------+-------------------+--------------------------------------+
-| ... `->` ...           | `lname`           | Number of bytes in the object name   |
-+--------------------+-------------------+--------------------------------------+
-| ... `->` ...           | `Name`            | `lName` bytes with the name of the   |
-|                    |                   | object                               |
-+--------------------+-------------------+--------------------------------------+
-| ... `->` ...           | `lTitle`          | Number of bytes in the object title  |
-+--------------------+-------------------+--------------------------------------+
-| ... `->` ...           | `Title`           | Title of the object                  |
-+--------------------+-------------------+--------------------------------------+
-| ... `->` ...           | `DATA`            | Data bytes associated to the object  |
-+--------------------+-------------------+--------------------------------------+
-
-You see a reference to **`TKey`**. It is explained in detail in the next
-section.
-
-### The Class Description List (StreamerInfo List)
-
-
-The histogram records are followed by the `StreamerInfo` list of class
-descriptions. The list contains the description of each class that has
-been written to file.
-
-``` {.cpp}
-20010404/092347  At:5854   N=2390   StreamerInfo   CX =  3.41
-```
-
-The class description is recursive, because to fully describe a class,
-its ancestors and object data members have to be described also. In
-`demo.root`, the class description list contains the description for:
-
--   **`TH1F`**
-
--   all classes in the **`TH1F`** inheritance tree
-
--   all classes of the object data members
-
--   all classes in the object data members' inheritance tree.
-
-This description is implemented by the **`TStreamerInfo`** class`,` and
-is often referred to as simply `StreamerInfo`. You can print a file's
-`StreamerInfo`list with the `TFile::ShowStreamerInfo` method. Below is
-an example of the output. Only the first line of each class description
-is shown. The `demo.root` example contains only **`TH1F`** objects. Here
-we see the recursive nature of the class description; it contains the
-`StreamerInfo`of all the classes needed to describe **`TH1F`**.
-
-``` {.cpp}
-root[] f.ShowStreamerInfo()
-StreamerInfo for class: TH1F, version=1
-  BASE     TH1         offset=0 type= 0 1-Dim histogram base class
-  BASE     TArrayF     offset=0 type= 0 Array of floats
-
-StreamerInfo for class: TH1, version=3
-  BASE     TNamed      offset=0 type=67 The basis for named object(name,title)
-  BASE     TAttLine    offset=0 type=0  Line attributes
-  BASE     TAttFill    offset=0 type=0  Fill area attributes
-  BASE     TAttMarker  offset=0 type=0  Marker attributes
-  Int_t    fNcells     offset=0 type=3  number bins(1D),cells(2D)+U/Overflows
-  TAxis    fXaxis      offset=0 type=61 X axis descriptor
-  TAxis    fYaxis      offset=0 type=61 Y axis descriptor
-  TAxis    fZaxis      offset=0 type=61 Z axis descriptor
-  Short_t  fBarOffset  offset=0 type=2  (1000*offset) for barcharts or legos
-  Short_t  fBarWidth   offset=0 type=2  (1000*width) for bar charts or legos
-  Stat_t   fEntries    offset=0 type=8  Number of entries//continued...
-  Stat_t   fTsumw      offset=0 type=8  Total Sum of weights
-  Stat_t   fTsumw2     offset=0 type=8  Total Sum of squares of weights
-  Stat_t   fTsumwx     offset=0 type=8  Total Sum of weight*X
-  Stat_t   fTsumwx2    offset=0 type=8  Total Sum of weight*X*X
-  Double_t fMaximum    offset=0 type=8  Maximum value for plotting
-  Double_t fMinimum    offset=0 type=8  Minimum value for plotting
-  Double_t fNormFactor offset=0 type=8  Normalization factor
-  TArrayD  fContour    offset=0 type=62 Array to display contour levels
-  TArrayD  fSumw2      offset=0 type=62 Array of sum of squares of weights
-  TString  fOption     offset=0 type=65 histogram options
-  TList*   fFunctions  offset=0 type=63 ->Pointer to list of functions(fits,user)
-
-StreamerInfo for class: TNamed, version=1
-...
-StreamerInfo for class: TAttLine, version=1
-...
-StreamerInfo for class: TAttFill, version=1
-...
-StreamerInfo for class: TAttMarker, version=1
-...
-StreamerInfo for class: TArrayF, version=1
-...
-StreamerInfo for class: TArray, version=1
-...
-StreamerInfo for class: TAxis, version=6
-...
-StreamerInfo for class: TAttAxis, version=4
-...
-```
-
-ROOT allows a class to have multiple versions, and each version has its
-own description in form of a `StreamerInfo`. Above you see the class
-name and version number. The `StreamerInfo`list has only one description
-for each class/version combination it encountered. The file can have
-multiple versions of the same class, for example objects of old and new
-versions of a class can be in the same file. The `StreamerInfo`is
-described in detail in the section on Streamers.
-
-### The List of Keys and the List of Free Blocks
-
-
-The last three entries on the output of `TFile::Map()` are the list of
-keys, the list of free segments, and the address where the data ends..
-When a file is closed, it writes a linked list of keys at the end of the
-file. This is what we see in the third to the last entry. In our
-example, the list of keys is stored in 732 bytes beginning at byte\#
-8244.
-
-``` {.cpp}
-20010404/092347    At:8244      N=732       KeysList
-20010404/092347    At:8976      N=53        FreeSegments
-20010404/092347    At:9029      N=1         END
-```
-
-The second to last entry is a list of free segments. In our case, this
-starts 8976 and is not very long, only 53 bytes, since we have not
-deleted any objects. The last entry is the address of the last byte in
-the file.
-
-### File Recovery
-
-
-A file may become corrupted or it may be impossible to write it to disk
-and close it properly. For example if the file is too large and exceeds
-the disk quota, or the job crashes or a batch job reaches its time limit
-before the file can be closed. In these cases, it is imperative to
-recover and retain as much information as possible. ROOT provides an
-intelligent and elegant file recovery mechanism using the redundant
-directory information in the record header.
-
-If a file that has been not properly closed is opened again, it is
-scanned and rebuilt according to the information in the record header.
-The recovery algorithm reads the file and creates the saved objects in
-memory according to the header information. It then rebuilds the
-directory and file structure. If the file is opened in write mode, the
-recovery makes the correction on disk when the file is closed; however
-if the file is opened in read mode, the correction can not be written to
-disk. You can also explicitly invoke the recovery procedure by calling
-the `TFile::Recover()` method. You can recover the directory structure,
-but you cannot save what you recovered to the file on disk. In the
-following example, we interrupted and aborted the previous ROOT session,
-causing the file not to be closed. When we start a new session and
-attempt to open the file, it gives us an explanation and status on the
-recovery attempt.
-
-``` {.cpp}
-root[] TFile f("demo.root")
-Warning in : file demo.root probably not closed, trying to recover successfully recovered 15 keys
-```
-
-## The Logical ROOT File: TFile and TKey
-
-
-We saw that the `TFile::Map()` method reads the file sequentially and
-prints information about each record while scanning the file. It is not
-feasible to support only sequential access and hence ROOT provides
-random or direct access, i.e. reading a specified object at a time. To
-do so, `TFile` keeps a list of **`TKeys`**, which is
-essentially an index to the objects in the file. The **`TKey`** class
-describes the record headers of objects in the file. For example, we can
-get the list of keys and print them. To find a specific object on the
-file we can use the **`TFile::Get()` method.**
-
-``` {.cpp}
-root[] TFile f("demo.root")
-root[] f.GetListOfKeys()->Print()
-TKey Name = h0, Title = histo nr:0, Cycle = 1
-TKey Name = h1, Title = histo nr:1, Cycle = 1
-TKey Name = h2, Title = histo nr:2, Cycle = 1
-TKey Name = h3, Title = histo nr:3, Cycle = 1
-TKey Name = h4, Title = histo nr:4, Cycle = 1
-TKey Name = h5, Title = histo nr:5, Cycle = 1
-TKey Name = h6, Title = histo nr:6, Cycle = 1
-TKey Name = h7, Title = histo nr:7, Cycle = 1
-TKey Name = h8, Title = histo nr:8, Cycle = 1
-TKey Name = h9, Title = histo nr:9, Cycle = 1
-TKey Name = h10, Title = histo nr:10, Cycle = 1
-TKey Name = h11, Title = histo nr:11, Cycle = 1
-TKey Name = h12, Title = histo nr:12, Cycle = 1
-TKey Name = h13, Title = histo nr:13, Cycle = 1
-TKey Name = h14, Title = histo nr:14, Cycle = 1
-root[] TH1F *h9 = (TH1F*)f.Get("h9");
-```
-
-The `TFile::Get()` finds the **`TKey`** object with name "`h9`". Using
-the **`TKey`** info it will import in memory the object in the file at
-the file address \#3352 (see the output from the `TFile::Map` above).
-This is done by the `Streamer` method that is covered in detail in a
-later section. Since the keys are available in a **`TList`** of
-**`TKeys` we can iterate over the list of keys:**
-
-``` {.cpp}
-{
-   TFile f("demo.root");
-   TIter next(f.GetListOfKeys());
-   TKey *key;
-   while ((key=(TKey*)next())) {
-      printf("key: %s points to an object of class: %s at %dn",
-      key->GetName(),
-      key->GetClassName(),key->GetSeekKey());
-   }
-}
-```
-
-The output of this script is:
-
-``` {.cpp}
-root[] .x iterate.C
-key: h0 points to an object of class: TH1F at 150
-key: h1 points to an object of class: TH1F at 503
-key: h2 points to an object of class: TH1F at 854
-key: h3 points to an object of class: TH1F at 1194
-key: h4 points to an object of class: TH1F at 1539
-key: h5 points to an object of class: TH1F at 1882
-key: h6 points to an object of class: TH1F at 2240
-key: h7 points to an object of class: TH1F at 2582
-key: h8 points to an object of class: TH1F at 2937
-key: h9 points to an object of class: TH1F at 3293
-key: h10 points to an object of class: TH1F at 3639
-key: h11 points to an object of class: TH1F at 3986
-key: h12 points to an object of class: TH1F at 4339
-key: h13 points to an object of class: TH1F at 4694
-key: h14 points to an object of class: TH1F at 5038
-```
-
-In addition to the list of keys, **`TFile`** also keeps two other lists:
-**`TFile`**`::fFree` is a **`TList`** of free blocks used to recycle
-freed up space in the file. ROOT tries to find the best free block. If a
-free block matches the size of the new object to be stored, the object
-is written in the free block and this free block is deleted from the
-list. If not, the first free block bigger than the object is used.
-`TFile::fListHead` contains a sorted list (**`TSortedList`**) of objects
-in memory. The diagram below illustrates the logical view of the
-**`TFile`** and **`TKey`**.
-
-![ROOT File/Directory/Key description](pictures/030000E7.png)
-
-### Viewing the Logical File Contents
-
-
-**`TFile`** is a descendent of **`TDirectory`**, which means it behaves
-like a **`TDirectory`**. We can list the contents, print the name, and
-create subdirectories. In a ROOT session, you are always in a directory
-and the directory you are in is called the current directory and is
-stored in the global variable ***`gDirectory`***. Let us look at a more
-detailed example of a ROOT file and its role as the current directory.
-First, we create a ROOT file by executing a sample script.
-
-``` {.cpp}
-root[] .x $ROOTSYS/tutorials/hsimple.C
-```
-
-Now you should have `hsimple.root` in your directory. The file was
-closed by the script so we have to open it again to work with it. We
-open the file with the intent to update it, and list its contents.
-
-``` {.cpp}
-root[] TFile f ("hsimple.root","UPDATE")
-root[] f.ls()
-TFile** hsimple.root
-TFile* hsimple.root
-KEY: TH1F hpx;1 This is the px distribution
-KEY: TH2F hpxpy;1 py vs px
-KEY: TProfile hprof;1 Profile of pz versus px
-KEY: TNtuple ntuple;1 Demo ntuple
-```
-
-It shows the two lines starting with **`TFile`** followed by four lines
-starting with the word "`KEY`". The four keys tell us that there are
-four objects on disk in this file. The syntax of the listing is:
-
-``` {.cpp}
-KEY:  ; 
-```
-
-For example, the first line in the list means there is an object in the
-file on disk, called `hpx`. It is of the class **`TH1F`**
-(one-dimensional histogram of floating numbers). The object's title is
-"This is the `px` distribution". If the line starts with `OBJ`, the
-object is in memory. The \<class\> is the name of the ROOT class
-(T-something). The \<variable\> is the name of the object. The cycle
-number along with the variable name uniquely identifies the object. The
-\<title\> is the string given in the constructor of the object as title.
-
-![The structure of TFile](pictures/030000E8.png)
-
-The figure shows a **`TFile`** with five objects in the top directory
-`(kObjA;1, kObjA;2, kObjB;1, kObjC;1` and `kObjD;1)`. `ObjA` is on file
-twice with two different cycle numbers. It also shows four objects in
-memory (`mObjE`, `mObjeF`, `mObjM`, `mObjL`). It also shows several
-subdirectories.
-
-### The Current Directory
-
-
-When you create a **`TFile`** object, it becomes the current directory.
-Therefore, the last file to be opened is always the current directory.
-To check your current directory you can type:
-
-``` {.cpp}
-root[] gDirectory->pwd()
-Rint:/
-```
-
-This means that the current directory is the ROOT session (`Rint`). When
-you create a file, and repeat the command the file becomes the current
-directory.
-
-``` {.cpp}
-root[] TFile f1("AFile1.root");
-root[] gDirectory->pwd()
-AFile1.root:/
-```
-
-If you create two files, the last becomes the current directory.
-
-``` {.cpp}
-root[] TFile f2("AFile2.root");
-root[] gDirectory->pwd()
-AFile2.root:/
-```
-
-To switch back to the first file, or to switch to any file in general,
-you can use the `TDirectory::cd` method. The next command changes the
-current directory back to the first file.
-
-``` {.cpp}
-root[] f1.cd();
-root[] gDirectory->pwd()
-AFile1.root:/
-```
-
-Note that even if you open the file in "READ" mode, it still becomes the
-current directory. Cling also offers a shortcut for `gDirectory->pwd()`
-and `gDirectory->ls()`, you can type:
-
-``` {.cpp}
-root[] .pwd
-AFile1.root:/
-root[] .ls
-TFile**        AFile1.root
-TFile*         AFile1.root
-```
-
-To return to the home directory where we were before:
-
-``` {.cpp}
-root[] gROOT->cd()
-(unsigned char)1
-root[] gROOT->pwd()
-Rint:/
-```
-
-### Objects in Memory and Objects on Disk
-
-
-The `TFile::ls()` method has an option to list the objects on disk
-("`-d`") or the objects in memory ("`-m`"). If no option is given it
-lists both, first the objects in memory, then the objects on disk. For
-example:
-
-``` {.cpp}
-root[] TFile *f = new TFile("hsimple.root");
-root[] gDirectory->ls("-m")
-TFile**         hsimple.root
-TFile*         hsimple.root
-```
-
-Remember that ***`gDirectory`*** is the current directory and at this
-time is equivalent to "`f`". This correctly states that no objects are
-in memory.
-
-The next command lists the objects on disk in the current directory.
-
-``` {.cpp}
-root[] gDirectory->ls("-d")
-TFile**         hsimple.root
-TFile*         hsimple.root
-KEY: TH1F     hpx;1    This is the px distribution
-KEY: TH2F     hpxpy;1  py vs px
-KEY: TProfile hprof;1  Profile of pz versus px
-KEY: TNtuple  ntuple;1 Demo ntuple
-```
-
-To bring an object from disk into memory, we have to use it or "Get" it
-explicitly. When we use the object, ROOT gets it for us. Any reference
-to `hprof` will read it from the file. For example drawing `hprof` will
-read it from the file and create an object in memory. Here we draw the
-profile histogram, and then we list the contents.
-
-``` {.cpp}
-root[] hprof->Draw()
-<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
-root[] f->ls()
-TFile** hsimple.root
-TFile* hsimple.root
-OBJ: TProfile hprof Profile of pz versus px : 0
-KEY: TH1F hpx;1 This is the px distribution
-KEY: TH2F hpxpy;1 py vs px
-KEY: TProfile hprof;1 Profile of pz versus px
-KEY: TNtuple ntuple;1 Demo ntuple
-```
-
-We now see a new line that starts with OBJ. This means that an object of
-class **`TProfile`**, called `hprof` has been added in memory to this
-directory. This new `hprof` in memory is independent from the `hprof` on
-disk. If we make changes to the `hprof` in memory, they are not
-propagated to the `hprof` on disk. A new version of `hprof` will be
-saved once we call `Write`.
-
-You may wonder why `hprof` is added to the objects in the current
-directory. `hprof` is of the class **`TProfile`** that inherits from
-**`TH1D`**, which inherits from **`TH1`**. **`TH1`** is the basic
-histogram. All histograms and trees are created in the current directory
-(also see "Histograms and the Current Directory"). The reference to "all
-histograms" includes objects of any class descending directly or
-indirectly from **`TH1`**. Hence, our **`TProfile`** `hprof` is created
-in the current directory `f.`There was another side effect when we
-called the `TH1::Draw` method. ROOT printed this statement:
-
-``` {.cpp}
-<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
-```
-
-It tells us that a **`TCanvas`** was created and it named it `c1`. This
-is where ROOT is being nice, and it creates a canvas for drawing the
-histogram if no canvas was named in the draw command, and if no active
-canvas exists. The newly created canvas, however, is NOT listed in the
-contents of the current directory. Why is that? The canvas is not added
-to the current directory, because by default ONLY histograms and trees
-are added to the object list of the current directory. Actually,
-**`TEventList`** objects are also added to the current directory, but at
-this time, we don't have to worry about those. If the canvas is not in
-the current directory then where is it? Because it is a canvas, it was
-added to the list of canvases.
-
-This list can be obtained by the command
-`gROOT->GetListOfCanvases()->ls()`. The `ls()` will print the contents
-of the list. In our list, we have one canvas called `c1`. It has a
-**`TFrame`**, a **`TProfile`**, and a **`TPaveStats`**.
-
-``` {.cpp}
-root[] gROOT->GetListOfCanvases()->ls()
-Canvas Name=c1 Title=c1
-Option=TCanvas fXlowNDC=0 fYlowNDC=0 fWNDC=1 fHNDC=1
-Name= c1 Title= c1
-Option=TFrame  X1= -4.000000 Y1=0.000000 X2=4.000000 Y2=19.384882
-OBJ: TProfile hprof   Profile of pz versus px : 0
-TPaveText  X1=-4.900000 Y1=20.475282 X2=-0.950000 Y2=21.686837 title
-TPaveStats X1=2.800000  Y1=17.446395 X2=4.800000  Y2=21.323371 stats
-```
-
-Lets proceed with our example and draw one more histogram, and we see
-one more OBJ entry.
-
-``` {.cpp}
-root[] hpx->Draw()
-root[] f->ls()
-TFile**         hsimple.root
-TFile*         hsimple.root
-OBJ: TProfile hprof    Profile of pz versus px : 0
-OBJ: TH1F     hpx      This is the px distribution : 0
-KEY: TH1F     hpx;1    This is the px distribution
-KEY: TH2F     hpxpy;1  py vs px
-KEY: TProfile hprof;1  Profile of pz versus px
-KEY: TNtuple  ntuple;1 Demo ntuple
-```
-
-`TFile::ls()` loops over the list of objects in memory and the list of
-objects on disk. In both cases, it calls the `ls()` method of each
-object. The implementation of the `ls` method is specific to the class
-of the object, all of these objects are descendants of **`TObject`** and
-inherit the **`TObject`**`::ls()` implementation. The histogram classes
-are descendants of **`TNamed`** that in turn is a descent of
-`TObject`. In this case, **`TNamed::ls()`** is executed, and
-it prints the name of the class, and the name and title of the object.
-Each directory keeps a list of its objects in the memory. You can get
-this list by **`TDirectory::GetList()`**. To see the lists in memory
-contents you can do:
-
-``` {.cpp}
-root[]f->GetList()->ls()
-OBJ: TProfile   hprof   Profile of pz versus px : 0
-OBJ: TH1F       hpx     This is the px distribution : 0
-```
-
-Since the file `f` is the current directory (***`gDirectory`***), this
-will yield the same result:
-
-``` {.cpp}
-root[] gDirectory->GetList()->ls()
-OBJ: TProfile   hprof   Profile of pz versus px : 0
-OBJ: TH1F       hpx     This is the px distribution : 0
-```
-
-### Saving Histograms to Disk
-
-
-At this time, the objects in memory (OBJ) are identical to the objects
-on disk (KEY). Let's change that by adding a fill to the `hpx` we have
-in memory.
-
-``` {.cpp}
-root[] hpx->Fill(0)
-```
-
-Now the `hpx` in memory is different from the histogram (`hpx`) on disk.
-Only one version of the object can be in memory, however, on disk we can
-store multiple versions of the object. The `TFile::Write` method will
-write the list of objects in the current directory to disk. It will add
-a new version of `hpx` and `hprof`.
-
-``` {.cpp}
-root[] f->Write()
-root[] f->ls()
-TFile**         hsimple.root
-TFile*         hsimple.root
-OBJ: TProfile hprof  Profile of pz versus px : 0
-OBJ: TH1F     hpx    This is the px distribution : 0
-KEY: TH1F     hpx;2  This is the px distribution
-KEY: TH1F     hpx;1  This is the px distribution
-KEY: TH2F     hpxpy;1 py vs px
-KEY: TProfile hprof;2 Profile of pz versus px
-KEY: TProfile hprof;1 Profile of pz versus px
-KEY: TNtuple  ntuple;1        Demo ntuple
-```
-
-![The file before and after the call to `Write`](pictures/030000E9.png)
-
-The `TFile::Write` method wrote the entire list of objects in the
-current directory to the file. You see that it added two new keys:
-`hpx;2` and `hprof;2` to the file. Unlike memory, a file is capable of
-storing multiple objects with the same name. Their cycle number, the
-number after the semicolon, differentiates objects on disk with the same
-name. If you wanted to save only `hpx` to the file, but not the entire
-list of objects, you could use the `TH1::Write `method of `hpx`:
-
-``` {.cpp}
-root[] hpx->Write()
-```
-
-A call to `obj->Write` without any parameters will call `obj->GetName()`
-to find the name of the object and use it to create a key with the same
-name. You can specify a new name by giving it as a parameter to the
-`Write` method.
-
-``` {.cpp}
-root[] hpx->Write("newName")
-```
-
-If you want to re-write the same object, with the same key, use the
-overwrite option.
-
-``` {.cpp}
-root[] hpx->Write("",TObject::kOverwrite)
-```
-
-If you give a new name and use the `kOverwrite`, the object on disk with
-the matching name is overwritten if such an object exists. If not, a new
-object with the new name will be created.
-
-``` {.cpp}
-root[] hpx->Write("newName",TObject::kOverwrite)
-```
-
-The `Write` method did not affect the objects in memory at all. However,
-if the file is closed, the directory is emptied and the objects on the
-list are deleted.
-
-``` {.cpp}
-root[] f->Close()
-root[] f->ls()
-TFile**     hsimple.root
-TFile*      hsimple.root
-```
-
-In the code snipped above, you can see that the directory is now empty.
-If you followed along so far, you can see that `c1` which was displaying
-`hpx` is now blank. Furthermore, `hpx` no longer exists.
-
-``` {.cpp}
-root[] hpx->Draw()
-Error: No symbol hpx in current scope
-```
-
-This is important to remember, do not close the file until you are done
-with the objects or any attempt to reference the objects will fail.
-
-### Histograms and the Current Directory
-
-
-When a histogram is created, it is added by default to the list of
-objects in the current directory. You can get the list of histograms in
-a directory and retrieve a pointer to a specific histogram.
-
-``` {.cpp}
-   TH1F *h = (TH1F*)gDirectory->Get("myHist"); // or
-   TH1F *h = (TH1F*)gDirectory->GetList()->FindObject("myHist");
-```
-
-The method `TDirectory::GetList()` returns a **`TList`** of objects in
-the directory. You can change the directory of a histogram with the
-`SetDirectory` method.
-
-``` {.cpp}
-   h->SetDirectory(newDir);
-```
-
-If the parameter is 0, the histogram is no longer associated with a
-directory.
-
-``` {.cpp}
-   h->SetDirectory(0);
-```
-
-Once a histogram is removed from the directory, it will no longer be
-deleted when the directory is closed. It is now your responsibility to
-delete this histogram object once you are finished with it. To change
-the default that automatically adds the histogram to the current
-directory, you can call the static function:
-
-``` {.cpp}
-   TH1::AddDirectory(kFALSE);
-```
-
-In this case, you will need to do all the bookkeeping for all the
-created histograms.
-
-### Saving Objects to Disk
-
-
-In addition to histograms and trees, you can save any object in a ROOT
-file. For example to save a canvas to the ROOT file you can use either
-**`TObject::Write()` or `TDirectory`**`::WriteTObject()`. The example:
-
-``` {.cpp}
-root[] c1->Write()
-```
-
-This is equivalent to:
-
-``` {.cpp}
-root[] f->WriteTObject(c1)
-```
-
-For objects that do not inherit from **`TObject`** use:
-
-``` {.cpp}
-root[] f->WriteObject(ptr,"nameofobject")
-```
-
-***`Another example:`***
-
-``` {.cpp}
-root[] TFile *f = new TFile("hsimple.root","UPDATE")
-root[] hpx->Draw()
-<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
-root[] c1->Write()
-root[] f->ls()
-TFile**        hsimple.root
-TFile*         hsimple.root
-OBJ: TH1F      hpx      This is the px distribution : 0
-KEY: TH1F     hpx;2   This is the px distribution
-KEY: TH1F     hpx;1   This is the px distribution
-KEY: TH2F     hpxpy;1 py vs px
-KEY: TProfile hprof;2 Profile of pz versus px
-KEY: TProfile hprof;1 Profile of pz versus px
-KEY: TNtuple  ntuple;1   Demo ntuple
-KEY: TCanvas  c1;1    c1
-```
-
-### Saving Collections to Disk
-
-
-All collection classes inherit from **`TCollection`** and hence inherit
-the **`TCollection::Write()` method. When you call
-`TCollection`**`::Write()` each object in the container is written
-individually into its own key in the file. To write all objects into one
-key you can specify the name of the key and use the
-option` TObject::kSingleKey`. For example:
-
-``` {.cpp}
-root[] TList * list = new TList;
-root[] TNamed * n1, * n2;
-root[] n1 = new TNamed("name1","title1");
-root[] n2 = new TNamed("name2","title2");
-root[] list->Add(n1);
-root[] list->Add(n2);
-root[] gFile->WriteObject(list,"list",TObject::kSingleKey);
-```
-
-### A TFile Object Going Out of Scope
-
-
-There is another important point to remember about `TFile::Close` and
-**`TFile::Write`**. When a variable is declared on the stack in a function
-such as in the code below, it will be deleted when it goes out of
-scope.
-
-``` {.cpp}
-void foo() {
-   TFile f("AFile.root","RECREATE");
-}
-```
-
-As soon as the function `foo `has finished executing, the variable `f`
-is deleted. When a **`TFile`** object is deleted an implicit call to
-`TFile::Close` is made. This will save only the file descriptor to disk.
-It contains the file header, the `StreamerInfo `list, the key list, the
-free segment list, and the end address. See "The Physical Layout of ROOT
-Files". The `TFile::Close` does not make a call to `Write()`, which
-means that the objects in memory will not be saved in the file. You need
-to explicitly call `TFile::Write()` to save the object in memory to file
-before the exit of the function.
-
-``` {.cpp}
-void foo() {
-   TFile f("AFile.root","RECREATE");
-   ... stuff ...
-   f.Write();
-}
-```
-
-To prevent an object in a function from being deleted when it goes out
-of scope, you can create it on the heap instead of on the stack. This
-will create a **`TFile`** object `f`, that is available on a global
-scope, and it will still be available when exiting the function.
-
-``` {.cpp}
-void foo() {
-   TFile *f = new TFile("AFile.root","RECREATE");
-}
-```
-
-### Retrieving Objects from Disk
-
-
-If you have a ROOT session running, please quit and start fresh.
-
-We saw that multiple versions of an object with the same name could be
-in a ROOT file. In our example, we saved a modified histogram `hpx` to
-the file, which resulted in two `hpx's` uniquely identified by the cycle
-number: `hpx;1` and `hpx;2`. The question is how we can retrieve the
-right version of `hpx`. When opening the file and using `hpx`, Cling
-retrieves the one with the highest cycle number. To read the `hpx;1`
-into memory, rather than the `hpx:2` we would get by default, we have to
-explicitly get it and assign it to a variable.
-
-``` {.cpp}
-root[] TFile *f1 = new TFile("hsimple.root")
-root[] TH1F *hpx1; f1->GetObject("hpx;1",hpx)
-root[] hpx1->Draw()
-```
-
-### Subdirectories and Navigation
-
-
-The **`TDirectory`** class lets you organize its contents into
-subdirectories, and **`TFile`** being a descendent of **`TDirectory`**
-inherits this ability. Here is an example of a ROOT file with multiple
-subdirectories as seen in the ROOT browser. To add a subdirectory to a
-file use `TDirectory::mkdir`. The example below opens the file for
-writing and creates a subdirectory called "Wed011003". Listing the
-contents of the file shows the new directory in the file and the
-**`TDirectory`** object in memory.
-
-``` {.cpp}
-root[] TFile *f = new TFile("AFile.root","RECREATE")
-root[] f->mkdir("Wed011003")
-(class TDirectory*)0x1072b5c8
-```
-
-``` {.cpp}
-root[] f->ls()
-TFile**         AFile.root
-TFile*          AFile.root
-TDirectory*           Wed011003       Wed011003
-KEY: TDirectory       Wed011003;1     Wed011003
-```
-
-We can change the current directory by navigating into the subdirectory,
-and after changing directory; we can see that ***`gDirectory`*** is now
-"`Wed011003`".
-
-``` {.cpp}
-root[] f->cd("Wed011003")
-root[] gDirectory->pwd()
-AFile.root:/Wed011003
-```
-
-In addition to ***`gDirectory`*** we have ***`gFile`***, another global
-that points to the current file. In our example, ***`gDirectory`***
-points to the subdirectory, and ***`gFile`*** points to the file (i.e.
-the files' top directory).
-
-``` {.cpp}
-root[] gFile->pwd()
-AFile.root:/
-```
-
-Use `cd()` without any arguments to return to the file's top directory.
-
-``` {.cpp}
-root[] f->cd()
-AFile.root:/
-```
-
-Change to the subdirectory again, and create a histogram. It is added to
-the current directory, which is the subdirectory "`Wed011003`".
-
-``` {.cpp}
-root[] f->cd("Wed011003")
-root[] TH1F *histo = new TH1F("histo","histo",10,0,10)
-root[] gDirectory->ls()
-TDirectory* Wed011003   Wed011003
-OBJ: TH1F      histo   histo : 0
-```
-
-If you are in a subdirectory and you want to have a pointer to the file
-containing the subdirectory, you can do:
-
-``` {.cpp}
-root[] gDirectory->GetFile()
-```
-
-If you are in the top directory ***`gDirectory`*** is the same as
-***`gFile`***. We write the file to save the histogram on disk, to show
-you how to retrieve it later.
-
-``` {.cpp}
-root[] f->Write()
-root[] gDirectory->ls()
-TDirectory*             Wed011003       Wed011003
-OBJ: TH1F      histo   histo : 0
-KEY: TH1F      histo;1 histo
-```
-
-When retrieving an object from a subdirectory, you can navigate to the
-subdirectory first or give it the path name relative to the file. The
-read object is created in memory in the current directory. In this first
-example, we get `histo` from the top directory and the object will be in
-the top directory.
-
-``` {.cpp}
-root[] TH1 *h; f->GetObject("Wed011003/histo;1",h)
-```
-
-If file is written, a copy of `histo` will be in the top directory. This
-is an effective way to copy an object from one directory to another. In
-contrast, in the code box below, `histo` will be in memory in the
-subdirectory because we changed the current directory.
-
-``` {.cpp}
-root[] f->cd("Wed011003")
-root[] TH1 *h; gDirectory->GetObject("histo;1",h)
-```
-
-Note that there is no warning if the retrieving was not successful. You
-need to explicitly check the value of h, and if it is null, the object
-could not be found. For example, if you did not give the path name the
-histogram cannot be found and the pointer to h is null:
-
-``` {.cpp}
-root[] TH1 *h; gDirectory->GetObject("Wed011003/histo;1",h)
-root[] h
-(class TH1*)0x10767de0
-root[] TH1 *h; gDirectory->GetObject("histo;1",h)
-root[] h
-(class TH1*)0x0
-```
-
-To remove a subdirectory you need to use `TDirectory::Delete`. There is
-no **`TDirectory::rmdir`**. The Delete method takes a string containing
-the variable name and cycle number as a parameter.
-
-``` {.cpp}
-void Delete(const char *namecycle)
-```
-
-The `namecycle` string has the format `name;cycle`. The next are some
-rules to remember:
-
--   `name` = \* means all, but don't remove the subdirectories
-
--   `cycle` =\* means all cycles (memory and file)
-
--   `cycle` ="" means apply to a memory object
-
--   `cycle` = 9999 also means apply to a memory object
-
--   `namecycle` = "" means the same as `namecycle` ="T\*"
-
--   `namecycle` = `T*` delete subdirectories
-
-For example to delete a directory from a file, you must specify the
-directory cycle:
-
-``` {.cpp}
-root[] f->Delete("Wed011003;1")
-```
-
-Some other examples of `namecycle` format are:
-
--   `foo`:delete the object named `foo` from memory
-
--   `foo;1`: delete the cycle 1 of the object named `foo` from the file
-
--   `foo;*`: delete all cycles of `foo` from the file and also from
-    memory
-
--   `*;2`: delete all objects with cycle number 2 from the file
-
--   `*;*:  delete` all objects from memory and from the file
-
--   `T*;*`: delete all objects from memory and from the file including
-    all subdirectories
-
-## Streamers
-
-
-To follow the discussion on `Streamers`, you need to know what a
-*simple* data type is. A variable is of a simple data type if it cannot
-be decomposed into other types. Examples of simple data types are longs,
-shorts, floats, and chars. In contrast, a variable is of a *composite*
-data type if it can be decomposed. For example, classes, structures, and
-arrays are composite types. Simple types are also called primitive
-types, basic types, and Cling sometimes calls them fundamental types.
-
-When we say, "writing an object to a file", we actually mean writing the
-current values of the data members. The most common way to do this is to
-decompose (also called the serialization of) the object into its data
-members and write them to disk. The decomposition is the job of the
-`Streamer`. Every class with ambitions to be stored in a file has a
-`Streamer `that decomposes it and "streams" its members into a buffer.
-
-The methods of the class are not written to the file, it contains only
-the persistent data members. To decompose the parent classes, the
-`Streamer `calls the `Streamer `of the parent classes. It moves up the
-inheritance tree until it reaches an ancestor without a parent. To
-serialize the object data members it calls their `Streamer`. They in
-turn move up their own inheritance tree and so forth. The simple data
-members are written to the buffer directly. Eventually the buffer
-contains all simple data members of all the classes that make up this
-particular object. Data members that are references (as
-`MyClass &fObj;`) are never saved, it is always the responsibility of
-the object's constructor to set them properly.
-
-### Automatically Generated Streamers
-
-
-A `Streamer `usually calls other `Streamers`: the `Streamer `of its
-parents and data members. This architecture depends on all classes
-having `Streamers`, because eventually they will be called. To ensure
-that a class has a `Streamer`, `rootcling` automatically creates one in
-the `ClassDef` macro that is defined in `$ROOTSYS/include/Rtypes.h`.
-`ClassDef` defines several methods for any class, and one of them is the
-`Streamer`. The automatically generated `Streamer `is complete and can
-be used as long as no customization is needed.
-
-The `Event` class is defined in `$ROOTSYS/test/Event.h`. Looking at the
-class definition, we find that it inherits from **`TObject`**. It is a
-simple example of a class with diverse data members.
-
-``` {.cpp}
-class Event : public TObject {
-private:
-   TDirectory    *fTransient;            ///<! current directory
-   Float_t     fPt;                   ///<! transient value
-char           fType[20];
-Int_t          fNtrack;
-Int_t          fNseg;
-Int_t          fNvertex;
-UInt_t         fFlag;
-Float_t        fTemperature;
-EventHeader    fEvtHdr;           //|| don't split
-TClonesArray  *fTracks;           //->
-TH1F          *fH;                //->
-Int_t          fMeasures[10];
-Float_t        fMatrix[4][4];
-Float_t       *fClosestDistance;  //[fNvertex]
-...
-```
-
-The Event class is added to the dictionary by the `rootcling`
-utility. This is the `rootcling` statement in the
-`$ROOTSYS/test/Makefile`:
-
-``` {.cpp}
-@rootcling -f EventDict.cxx -c Event.h EventLinkDef.h
-```
-
-The `EventDict.cxx` file contains the automatically generated
-`Streamer `for Event:
-
-``` {.cpp}
-void Event::Streamer(TBuffer &R__b){
-   // Stream an object of class Event.
-   if (R__b.IsReading()) {
-      Event::Class()->ReadBuffer(R__b, this);
-   } else {
-      Event::Class()->WriteBuffer(R__b, this);
-   }
-}
-```
-
-When writing an `Event` object, `TClass::WriteBuffer` is called.
-`WriteBuffer` writes the current version number of the `Event class,`
-and its contents into the buffer `R__b`. The `Streamer `calls
-**`TClass::ReadBuffer`** when reading an `Event` object. The `ReadBuffer`
-method reads the information from buffer `R__b` into the `Event`
-object.
-
-### Transient Data Members (//!)
-
-
-To prevent a data member from being written to the file, insert a "`!`"
-To make it compatible with Doxygen, write `///<!` instead of `//!`.
-as the first character after the comment marks. It tells ROOT not to
-save that data member in a root file when saving the class. For example,
-in this version of Event, the `fPt` and `fTransient` data members are
-not persistent.
-
-``` {.cpp}
-class Event : public TObject {
-private:
-   TDirectory    *fTransient; ///<! current directory
-   Float_t fPt;               ///<! transient value
-...
-```
-
-### The Pointer to Objects (//-\>)
-
-
-The string "`->`" in the comment field of the members `*fH` and
-`*fTracks` instruct the automatic `Streamer` to assume these will point
-to valid objects and the `Streamer `of the objects can be called rather
-than the more expensive `R__b << fH`. It is important to note that no
-check is done on the validity of the pointer value. In particular if the
-pointer points, directly or indirectly, back to the current object, this
-will result in an infinite recursion and the abrupt end of the process.
-
-``` {.cpp}
-TClonesArray  *fTracks;            //->
-TH1F          *fH;                 //->
-```
-
-### Variable Length Array
-
-
-When the `Streamer `comes across a pointer to a simple type, it assumes
-it is an array. Somehow, it has to know how many elements are in the
-array to reserve enough space in the buffer and write out the
-appropriate number of elements. This is done in the class definition.
-For example:
-
-``` {.cpp}
-class Event : public TObject {
-private:
-   char           fType[20];
-   Int_t          fNtrack;
-   Int_t          fNseg;
-   Int_t          fNvertex;
-...
-   Float_t       *fClosestDistance;   //[fNvertex]
-```
-
-The array `fClosestDistance` is defined as a pointer of floating point
-numbers. A comment mark (//), and the number in square brackets tell the
-`Streamer `the length of the array for this object. In general the
-syntax is:
-
-``` {.cpp}
-<simple type> *<name>//[<length>]
-```
-
-The length cannot be an expression. If a variable is used, it needs to
-be an integer data member of the class. It must be defined ahead of its
-use, or in a base class.
-
-The same notation also applies to variable length array of object and
-variable length array of pointer to objects.
-
-``` {.cpp}
-MyObject *obj; //[fNojbs]
-MyObject **objs; //[fDatas]
-```
-
-### Double32\_t
-
-
-Math operations very often require double precision, but on saving
-single usually precision is sufficient. For this purpose we support the
-typedef Double32\_t which is stored in memory as a double and on disk as
-a float or integer. The actual size of disk (before compression) is
-determined by the parameter next to the data member declaration. For
-example:
-
-``` {.cpp}
-Double32_t m_data;     //[min,max<,nbits>]
-```
-
-If the comment is absent or does not contain `min`, `max`,
-`nbits`, the member is saved as a `float`.
-
-If `min` and `max` are present, they are saved with 32 bits precision.
-`min` and `max` can be explicit values or expressions of values known
-to Cling (e.g. `pi`).
-
-If `nbits` is present, the member is saved as `int` with `nbits` bits precision. For
-more details see the io tutorials `double32.C`.
-
-![Compression and precision of Double32\_t](pictures/030000EA.png)
-
-### Prevent Splitting (//|| )
-
-
-If you want to prevent a data member from being split when writing it to
-a tree, append the characters || right after the comment string. This
-only makes sense for object data members. For example:
-
-``` {.cpp}
-EventHeader    fEvtHdr;       //|| do not split the header
-```
-
-### Streamers with Special Additions
-
-
-Most of the time you can let `rootcling` generate a `Streamer` for you.
-However if you want to write your own `Streamer `you can do so. For some
-classes, it may be necessary to execute some code before or after the
-read or write block in the automatic `Streamer`. For example after the
-execution of the read block, one can initialize some non persistent
-members. There are two reasons why you would need to write your own
-Streamer: 1) if you have a non-persistent data member that you want to
-initialize to a value depending on the read data members; 2) if you want
-or need to handle the schema evolution on your own.  Note that an alternative
-for those cases is to consider write a schema evolution rule.
-
-First, you need to tell `rootcling` not to build a `Streamer `for you.
-The input to the `rootcling` command (in the `makefile`) is a list of
-classes in a `LinkDef.h` file. For example, the list of classes for
-`Event` is listed in `$ROOTSYS/test/EventLinkDef.h`. The "`-`" at the
-end of the class name tells `rootcling` not to generate a `Streamer`. In
-the example, you can see the `Event` class is the only one for which
-`rootcling` is instructed not to generate a `Streamer`.
-
-``` {.cpp}
-#ifdef __ROOTCLING__
-
-#pragma link off all globals;
-#pragma link off all classes;
-#pragma link off all functions;
-#pragma link C++ class EventHeader+;
-#pragma link C++ class Event-;
-#pragma link C++ class HistogramManager+;
-#pragma link C++ class Track+;
-
-#endif
-#pragma link C++ class EventHeader+;
-```
-
-The "`+`" sign tells `rootcling` to use the new `Streamer `system
-introduced in ROOT 3.0. The following is an example of a customized
-`Streamer `for `Event`. The `Streamer` takes a **`TBuffer`** as a
-parameter, and first checks to see if this is a case of reading or
-writing the buffer.
-
-``` {.cpp}
-void Event::Streamer(TBuffer &R__b) {
-   if (R__b.IsReading()) {
-      Event::Class()->ReadBuffer(R__b, this);
-      fTransient = gDirectory;       //save current directory
-      fPt= TMath::Sqrt(fPx*fPx + fPy*fPy + fPz*fPz);
-   } else {
-      Event::Class()->WriteBuffer(R__b, this);
-   }
-}
-```
-
-### Writing Objects
-
-
-The `Streamer` decomposes the objects into data members and writes them
-to a buffer. It does not write the buffer to a file, it simply populates
-a buffer with bytes representing the object. This allows us to write the
-buffer to a file or do anything else we could do with the buffer. For
-example, we can write it to a socket to send it over the network. This
-is beyond the scope of this chapter, but it is worthwhile to emphasize
-the need and advantage of separating the creation of the buffer from its
-use. Let us look how a buffer is written to a file. The dictionary for a
-class needs to be loaded before any object of that type can be saved.
-
-The `TObject::Write` method does the following:
-
--   Creates a **`TKey`** object in the current directory
-
--   Creates a **`TBuffer`** object which is part of the newly created
-    **`TKey`**
-
--   Fills the **`TBuffer`** with a call to the `class::Streamer` method
-
--   Creates a second buffer for compression, if needed
-
--   Reserves space by scanning the **`TFree`** list. At this point, the
-    size of the buffer is known.
-
--   Writes the buffer to the file
-
--   Releases the **`TBuffer`** part of the key
-
-In other words, the `TObject::Write` calls the `Streamer` method of the
-class to build the buffer. The buffer is in the key and the key is
-written to disk. Once written to disk the memory consumed by the buffer
-part is released. The key part of the **`TKey`** is kept.
-
-![A diagram of a streamed TH1F in the buffer](pictures/020000EB.jpg)
-
-The key consumes about 60 bytes, whereas the buffer, since it contains
-the object data, can be very large.
-
-### Ignore Object Streamers
-
-
-Your class can ignore the **`TObject`** `Streamer `with the
-`MyClass->Class::IgnoreObjectStreamer()` method. When the class
-`kIgnoreTObjectStreamer `bit is set (by calling the
-`IgnoreTObjectStreamer `method`)`, the automatically generated
-`Streamer `will not call `TObject::Streamer`, and the **`TObject`** part
-of the class is not streamed to the file. This is useful in case you do
-not use the **`TObject`** `fBits` and `fUniqueID `data members. You gain
-space on the file, and you do not loose functionality if you do not use
-the `fBits` and `fUniqueID. `See "The Role of TObject" on the use of
-`fBits` and `fUniqueID`.
-
-### Streaming a TClonesArray
-
-
-When writing a **`TClonesArray`** it bypasses by default the
-`Streamer `of the member class and uses a more efficient internal
-mechanism to write the members to the file. You can override the default
-and specify that the member class `Streamer `is used by setting the
-`TClonesArray::BypassStreamer` bit to false:
-
-``` {.cpp}
-   TClonesArray *fTracks;
-   fTracks->BypassStreamer(kFALSE);    // use the member Streamer
-```
-
-When the `kBypassStreamer` bit is set, the automatically generated
-`Streamer `can call directly the method **`TClass::WriteBuffer`**.
-Bypassing the `Streamer` improves the performance when writing/reading
-the objects in the **`TClonesArray`**. However, the drawback is when a
-**`TClonesArray`** is written with `split=0` bypassing the `Streamer`,
-the `StreamerInfo `of the class in the array being optimized, one cannot
-later use the **`TClonesArray`** with `split > 0`. For example, there is
-a problem with the following scenario: a class `Foo` has a
-**`TClonesArray`** of `Bar` objects the `Foo` object is written with
-`split=0` to `Tree` `T1`. In this case the `StreamerInfo` for the class
-`Bar` is created in optimized mode in such a way that data members of
-the same type are written as an array improving the I/O performance. In
-a new program, `T1` is read and a new `Tree` `T2` is created with the
-object `Foo` in `split > 1`.
-
-When the `T2 `branch is created, the `StreamerInfo` for the class `Bar`
-is created with no optimization (mandatory for the split mode). The
-optimized Bar `StreamerInfo` is going to be used to read the
-**`TClonesArray`** in `T1`. The result will be `Bar` objects with data
-member values not in the right sequence. The solution to this problem is
-to call `BypassStreamer(kFALSE)` for the **`TClonesArray`**. In this
-case, the normal `Bar::Streamer` function will be called. The
-`Bar::Streamer` function works OK independently if the `Bar`
-`StreamerInfo `had been generated in optimized mode or not.
-
-## Pointers and References in Persistency
-
-
-An object pointer as a data member presents a challenge to the streaming
-software. If the object pointed to is saved every time, it could create
-circular dependencies and consume a large amount of disk space. The
-network of references must be preserved on disk and recreated upon
-reading the file.
-
-If you use independent I/O operations for pointers and their referenced
-objects you can use the **`TRef`** class. Later in this section is an
-example that compares disk space, memory usage, and I/O times of C++
-pointers and **`TRef`**`s`. In general, a **`TRef`** is faster than C++
-but the advantage of a C++ pointer is that it is already C++.
-
-### Streaming C++ Pointers
-
-
-When ROOT encounters a pointer data member it calls the `Streamer` of
-the object and labels it with a unique object identifier. The object
-identifier is unique for one I/O operation. If there is another pointer
-to the object in the same I/O operation, the first object is referenced
-i.e. it is not saved again. When reading the file, the object is rebuilt
-and the references recalculated.
-
-![Streaming object pointers](pictures/020000EC.jpg)
-
-In this way, the network of pointers and their objects is rebuilt and
-ready to use the same way it was used before it was persistent. If the
-pointer hold the address of an object which in embedded in another
-object (as opposed to being pointed to by a pointer), the object will be
-duplicate at read time. To avoid this, make the pointer a transient data
-member.
-
-### Motivation for the TRef Class
-
-
-If the object is split into several files or into several branches of
-one or more `TTrees`, standard C++ pointers cannot be used because each
-I/O operation will write the referenced objects, and multiple copies
-will exist. In addition, if the pointer is read before the referenced
-object, it is null and may cause a run time system error. To address
-these limitations, ROOT offers the **`TRef`** class.
-
-**`TRef`** allows referencing an object in a different branch and/or in
-a different file. **`TRef`** also supports the complex situation where a
-**`TFile`** is updated multiple times on the same machine or a different
-machine. When a **`TRef`** is read before its referenced object, it is
-null. As soon as the referenced object is read, the **`TRef`** points to
-it. In addition, one can specify an action to be taken by **`TRef`** in
-the case it is read before its reference object (see"Action on Demand"
-below).
-
-### Using TRef
-
-
-A **`TRef`** is a lightweight object pointing to any **`TObject`**. This
-object can be used instead of normal C++ pointers in case:
-
--   The referenced object R and the pointer P are not written to the
-    same file
-
--   P is read before R
-
--   R and P are written to different Tree branches
-
-Below is a line from the example in `$ROOTSYS/test/Event.cxx.`
-
-``` {.cpp}
-   TRef   fLastTrack;             //pointer to last track
-...
-   Track *track = (Track*)fTracks->ConstructedAt(fNtrack++);
-   track->Set(random);
-   // Save reference to last Track in the collection of Tracks
-   fLastTrack = track;
-```
-
-The `track` and its reference `fLastTrack` can be written with two
-separate I/O calls in the same or in different files, in the same or in
-different branches of a **`TTree`**. If the **`TRef`** is read and the
-referenced object has not yet been read, **`TRef`** will return a null
-pointer. As soon as the referenced object will be read, **`TRef`** will
-point to it.
-
-### How Does It Work?
-
-
-A **`TRef`** is itself a **`TObject`** with an additional transient
-pointer `fPID`. When a **`TRef`** is used to point to a
-**`TObject`**` *R`, for example in a class with
-
-``` {.cpp}
-   TRef  P;
-```
-
-one can do:
-
-``` {.cpp}
-   P = R;      //to set the pointer
-```
-
-When the statement `P = R `is executed, the following happens:
-
--   The pointer `fPID` is set to the current `TProcessID (see below)`.
-
--   The current `ObjectNumber` (see below) is incremented by one.
-
--   `R.fUniqueID` is set to `ObjectNumber`.
-
--   In the `fPID` object, the element `fObjects[ObjectNumber]` is set to
-    `R`
-
--   `P.fUniqueID` is also set to `ObjectNumber`.
-
-After having set `P`, one can immediately return the value of `R` using
-`P.GetObject()`. This function returns the `fObjects[fUniqueID]` from
-the `fPID` object.
-
-When the **`TRef`** is written, the process id number `pidf` of `fPID`
-is written in addition to the **`TObject`** part of the **`TRef`**
-(`fBits,fUniqueID`). When the **`TRef`** is read, its pointer `fPID` is
-set to the value stored in the **`TObjArray`** of
-`TFile::fProcessIDs `(`fProcessIDs[pidf]`).
-
-When a referenced object is written, `TObject::Streamer` writes the
-`pidf` in addition to the standard `fBits and fUniqueID`. When
-`TObject::Streamer` reads a reference object, the `pidf` is read. At
-this point, the referenced object is entered into the table of objects
-of the **`TProcessID`** corresponding to `pidf`.
-
-WARNING: If `MyClass` is the class of the referenced object, The
-**`TObject`** part of `MyClass` must be streamed. One should not call
-`MyClass::Class()->IgnoreTObjectStreamer()`.
-
-#### TProccessID and TUUID
-
-A **`TProcessID`** uniquely identifies a ROOT job. The **`TProcessID`**
-title consists of a **`TUUID`** object, which provides a globally unique
-identifier. The **`TUUID`** class implements the UUID (Universally
-Unique Identifier), also known as GUID (Globally Unique Identifier). A
-UUID is 128 bits long, and if generated according to this algorithm, is
-either guaranteed to be different from all other UUID generated until
-3400 A.D. or extremely likely to be different.
-
-The **`TROOT`** constructor automatically creates a **`TProcessID`**.
-When a **`TFile`** contains referenced objects, the **`TProcessID`**
-object is written to the file. If a file has been written in multiple
-sessions (same machine or not), a **`TProcessID`** is written for each
-session. The **`TProcessID`** objects are used by **`TRef`** to uniquely
-identify the referenced **`TObject`**.
-
-When a referenced object is read from a file (its bit `kIsReferenced` is
-set), this object is entered into the objects table of the corresponding
-**`TProcessID`**. Each **`TFile`** has a list of **`TProcessIDs`** (see
-`TFile::fProcessIDs`) also accessible from `TProcessID::fgPIDs`
-(for all files). When this object is deleted, it is removed from the
-table via the cleanup mechanism invoked by the **`TObject`** destructor.
-Each **`TProcessID`** has a table (`TObjArray *fObjects`) that keeps
-track of all referenced objects. If a referenced object has a
-`fUniqueID`, a pointer to this unique object may be found using
-`fObjects->At(fUniqueID)`. In the same way, when a **`TRef::GetObject`**
-is called, `GetObject` uses its own `fUniqueID` to find the pointer to
-the referenced object. See `TProcessID::GetObjectWithID` and
-`PutObjectWithID`.
-
-#### Object Number
-
-When an object is referenced, a unique identifier is computed and stored
-in both the `fUniqueID` of the referenced and referencing object. This
-`uniqueID` is computed by incrementing by one the static global in
-`TProcessID::fgNumber`. The `fUniqueID` is the serial object number in
-the current session. One can retrieve the current `fgNumber` value by
-calling the static function `TProcessID::GetObjectCount` at any time or
-can set this number by **`TProcessID::SetObjectCount`**. To avoid a
-growing table of `fObjects` in `TProcessID`, in case, for example, one
-processes many events in a loop, it might be necessary to reset the
-object number at the end of processing of one event. See an example in
-`$ROOTSYS/test/Event.cxx` (look at function `Build`). The value of
-`ObjectNumber `may be saved at the beginning of one event and reset to
-this original value at the end of the event. These actions may be
-nested.
-
-``` {.cpp}
-   saveNumber = TProcessID::GetObjectCount();
-...
-   TProcessID::SetObjectCount(savedNumber);
-```
-
-### Action on Demand
-
-
-The normal behavior of a **`TRef`** has been described above. In
-addition, **`TRef`** supports "Actions on Demand". It may happen that
-the referenced object is not yet in the memory, on a separate file or
-not yet computed. In this case, **`TRef`** is able to execute
-automatically an action:
-
--   Call to a compiled function (static function of member function)
-
--   Call to an interpreted function
-
--   Execution of a Cling script
-
-#### How to Select This Option?
-
-In the definition of the **`TRef`** data member in the original class,
-do:
-
-``` {.cpp}
-    TRef fRef;   //EXEC:execName points to something
-```
-
-When the special keyword `"EXEC:"` is found in the comment field of the
-member, the next string is assumed to be the name of a **`TExec`**
-object. When a file is connected, the dictionary of the classes on the
-file is read in memory (see **`TFile::ReadStreamerInfo).` When the
-`TStreamerElement`** object is read, a **`TExec`** object is
-automatically created with the name specified after the keyword
-`"EXEC:"` in case a **`TExec`** with a same name does not already exist.
-
-The action to be executed via `this` **`TExec`** can be specified with:
-
--   A call to the **`TExec`** constructor, if the constructor is called
-    before
-
--   Opening the file.
-
--   A call to `TExec::SetAction` at any time.
-
-One can compute a pointer to an existing **`TExec`** with a name with:
-
-``` {.cpp}
-   TExec *myExec = gROOT->GetExec(execName);
-   myExec->SetAction(actionCommand);
-```
-
-The parameter `actionCommand` is a string containing a Cling instruction.
-Examples:
-
-``` {.cpp}
-   myExec->SetAction("LoadHits()");
-   myExec->SetAction(".x script.C");
-```
-
-When a `TRef` is de-referenced via **`TRef::GetObject`, its
-**`TExec`** is automatically executed. The **`TExec`** function/script
-can do one or more of the following:**
-
--   Load a file containing the referenced object. This function
-    typically looks in the file catalog.
-
--   Compute a pointer to the referenced object and communicate this
-    pointer back to the calling function **`TRef`**`::SetObject` via:
-
-``` {.cpp}
-   TRef::SetObject(object)
-```
-
-As soon as an object is returned to `GetObject`, the `fUniqueID` of the
-**`TRef`** is set to the `fUniqueID` of the referenced object. At the
-next call to `GetObject`, the pointer stored in
-`fPid:fObjects[fUniqueID]` will be returned directly. An example of
-action on demand is in `$ROOTSYS/test/Event.h`:
-
-``` {.cpp}
-   TRef    fWebHistogram;       //EXEC:GetWebHistogram
-```
-
-When calling `fWebHistogram.GetObject()`, the function `GetObject` will
-automatically invoke the script `GetWebHistogram.C` via the interpreter.
-An example of a `GetWebHistogram.C` script is shown below:
-
-``` {.cpp}
-void GetWebHistogram() {
-   TFile *f=TFile::Open("http://root.cern.ch/files/pippa.root");
-   f->cd("DM/CJ");
-   TH1 *h6 = (TH1*)gDirectory->Get("h6");
-   h6->SetDirectory(0);
-   delete f;
-   TRef::SetObject(h6);
-}
-```
-
-In the above example, a call to `fWebHistogram.GetObject()` executes the
-script with the function `GetWebHistogram`. This script connects a file
-with histograms: `pippa.root` on the ROOT Web site and returns the
-object `h6` to **`TRef`**`::GetObject`.
-
-``` {.cpp}
- TRef    fWebHistogram;           //EXEC:GetWebHistogram()
-```
-
-Note that if the definition of the `TRef fWebHistogram` had been changed
-the compiled or interpreted function `GetWebHistogram()` would have been
-called instead of the Cling script `GetWebHistogram.C.`
-
-### Array of TRef
-
-
-When storing multiple **`TRef`**s, it is more efficient to use a
-**`TRefArray`**. The efficiency is due to having a single pointer `fPID`
-for all `TRefs` in the array. It has a dynamic compact table of
-`fUniqueIDs`. We recommend that you use a **`TRefArray`** rather then a
-collection of `TRefs`.
-
-Example:
-
--   Suppose a `TObjArray *mytracks` containing a list of `Track`
-    objects.
-
--   Suppose a `TRefArray *pions` containing pointers to the pion tracks
-    in `mytracks`. This list is created with statements like:
-    `pions->Add(track);`
-
--   Suppose a `TRefArray *muons` containing pointers to the muon tracks
-    in `mytracks`.
-
-The 3 arrays `mytracks`,` pions` and `muons` may be written separately.
-
-## Schema Evolution
-
-
-Schema evolution is a problem faced by long-lived data. When a schema
-changes, existing persistent data can become inaccessible unless the
-system provides a mechanism to access data created with previous
-versions of the schema. In the lifetime of collaboration, the class
-definitions (i.e. the schema) are likely to change frequently. Not only
-can the class itself change, but any of its parent classes or data
-member classes can change also. This makes the support for schema
-evolution necessary.
-
-ROOT fully supports schema evolution. The next figure below illustrates
-some of the scenarios.
-
-![The ROOT schema evolution](pictures/020000ED.jpg)
-
-The top half represents different versions of the shared library with
-the class definitions. These are the in-memory class versions. The
-bottom half represents data files that contain different versions of the
-classes.
-
--   An old version of a shared library and a file with new class
-    definitions - this can be the case when someone has not updated the
-    library and is reading a new file.
-
--   Reading a file with a shared library that is missing a class
-    definition (i.e. missing class D).
-
--   Reading a file without any class definitions. This can be the case
-    where the class definition is lost, or unavailable.
-
--   The current version of a shared library and an old file with old
-    class versions (backward compatibility). This is often the case when
-    reading old data.
-
--   Reading a file with a shared library built with `MakeProject`. This
-    is the case when someone has already read the data without a shared
-    library and has used ROOT `MakeProject` feature to reconstruct the
-    class definitions and shared library (`MakeProject` is explained in
-    detail later on).
-
-In case of a mismatch between the in-memory version and the persistent
-version of a class, ROOT maps the persistent one to the one in memory.
-This allows you to change the class definition at will, for example:
-
--   Change the order of data members in the class.
-
--   Add new data members. By default, the value of the missing member
-    will be 0 or in case of an object it will be set to null.
-
--   Remove data members.
-
--   Move a data member to a base class or vice-versa.
-
--   Change the type of a member if it is a simple type or a pointer to a
-    simple type. If a loss of precision occurs, a warning is given.
-
--   Add or remove a base class
-
-![The schema evolution for objects written on disk and in memory](pictures/020000EE.jpg)
-
-ROOT supports schema evolution by keeping a class description of each
-version of the class that was ever written to disk, with the class. When
-it writes an object to file, it also writes the description of the
-current class version along with it. This description is implemented in
-the `StreamerInfo `class.
-
-### The TStreamerInfo Class
-
-
-Each class has a list of `StreamerInfo` objects, one for each version of
-the class if that version was written to disk at least once. When
-reading an object from a file, the system uses the `StreamerInfo` list
-to decode an object into the current version. The `StreamerInfo` is made
-up of **`TStreamerElements`** . Each describes one persistent data
-member of the class. By default, all data members of a class are
-persistent. To exclude a data member (i.e. make it not persistent), add
-a "`!`" after the comment marks. For example the pointer \*`fPainter` of
-a **`TH1`** is not persistent:
-
-``` {.cpp}
-   TVirtualHistPainter* fPainter ///<!pointer to histogram painter
-```
-
-### The TStreamerElement Class
-
-
-A **`TStreamerElement`** describes a data member of a simple type,
-object, array, pointer, or container. The offset in the
-**`TStreamerElement`** is the starting address of the data for that data
-member.
-
-``` {.cpp}
-BASE   TNamed        offset=  0 type=67 The basis for a named object
-BASE   TAttLine      offset= 28 type= 0 Line attributes
-```
-
-In this example, the **`TNamed`** data starts at byte 0, and
-**`TAttLine`** starts at byte 28. The offset is machine and compiler
-dependent and is computed when the `StreamerInfo` is analyzed. The types
-are defined in the file `TStreamerInfo.h` and listed here:
-
-``` {.cpp}
-enum EReadWrite {
-kBase=0,   kChar=1,kShort=2,kInt=3,kLong=4,
-kFloat=5,         kCounter=6,kCharStar=7, kDouble=8,kUChar=11,
-kUShort=12,         kUInt=13,kULong=14,kBits=15,kOffsetL=20,
-kOffsetP=40,  kObject=61,kAny=62,kObjectp=63,kObjectP=64,
-kTString=65,  kTObject=66,kTNamed=67,kSkip=100,kSkipL=120,
-kSkipP=140,    kConv=200,       kConvL=220,kConvP=240,kStreamer=500,
-kStreamLoop=501,    kMissing=99999
-};
-```
-
-The method `TClass::GetStreamerInfo` analyzes the `StreamerInfo` the
-same way it would be analyzed by referring to the class. While analyzing
-the `StreamerInfo`, it computes the offsets. The type field is the type
-of the **`TStreamerElement`**. It is specific to the `StreamerInfo`
-definition.
-
-### Example: TH1 StreamerInfo
-
-
-In the `StreamerInfo` of the **`TH1`** class we see the four base
-classes: **`TNamed`**, **`TAttLine`**, **`TAttFill`**,
-`and `**`TAttMarker`**. These are followed by a list of the data
-members. Each data member is implemented by a **`TStreamerElement`**
-object.
-
-``` {.cpp}
-root[] TH1::Class()->GetStreamerInfo()->ls()
-StreamerInfo for class: TH1, version=3
-BASE    TNamed  offset=  0 type=67 The basis for a named object
-BASE    TAttLine      offset= 28 type= 0 Line attributes
-BASE    TAttFill      offset= 40 type= 0 Fill area attributes
-BASE    TAttMarker    offset= 48 type= 0 Marker attributes
-Int_t   fNcells       offset= 60 type= 3 number of bins(1D
-TAxis   fXaxis        offset= 64 type=61 X axis descriptor
-TAxis   fYaxis        offset=192 type=61 Y axis descriptor
-TAxis   fZaxis        offset=320 type=61 Z axis descriptor
-Short_t fBarOffset    offset=448 type= 2(1000*offset)for bar charts or legos
-Short_t fBarWidth     offset=450 type= 2 (1000*width)for bar charts or legos
-Stat_t  fEntries      offset=452 type= 8 Number of entries
-Stat_t  fTsumw        offset=460 type= 8 Total Sum of weights
-Stat_t  fTsumw2       offset=468 type= 8 Total Sum of squares of weights
-Stat_t  fTsumwx       offset=476 type= 8 Total Sum of weight*X
-Stat_t  fTsumwx2      offset=484 type= 8 Total Sum of weight*X*X
-Double_t fMaximum     offset=492 type= 8 Maximum value for plotting
-Double_t fMinimum     offset=500 type= 8 Minimum value for plotting
-Double_t fNormFactor  offset=508 type= 8 Normalization factor
-TArrayD  fContour     offset=516 type=62 Array to display contour levels
-TArrayD  fSumw2       offset=528 type=62 Array of sum of squares of weights
-TString  fOption      offset=540 type=65 histogram options
-TList*   fFunctions   offset=548 type=63 ->Pointer to list of functions
-i= 0, TNamed       type= 67, offset=  0, len=1, method=0
-i= 1, TAttLine     type=  0, offset= 28, len=1, method=142484480
-i= 2, TAttFill     type=  0, offset= 40, len=1, method=142496992
-i= 3, TAttMarker   type=  0, offset= 48, len=1, method=142509704
-i= 4, fNcells      type=  3, offset= 60, len=1, method=0
-i= 5, fXaxis       type= 61, offset= 64, len=1, method=1081287424
-i= 6, fYaxis       type= 61, offset=192, len=1, method=1081287548
-i= 7, fZaxis       type= 61, offset=320, len=1, method=1081287676
-i= 8, fBarOffset   type= 22, offset=448, len=2, method=0
-i= 9, fEntries     type= 28, offset=452, len=8, method=0
-i=10, fContour     type= 62, offset=516, len=1, method=1081287804
-i=11, fSumw2       type= 62, offset=528, len=1, method=1081287924
-i=12, fOption      type= 65, offset=540, len=1, method=1081288044
-i=13, fFunctions   type= 63, offset=548, len=1, method=1081288164
-```
-
-### Optimized StreamerInfo
-
-
-The entries starting with "`i = 0`" is the optimized format of the
-`StreamerInfo`. Consecutive data members of the same simple type and
-size are collapsed and read at once into an array for performance
-optimization.
-
-``` {.cpp}
-i= 0, TNamed       type= 67, offset=  0, len=1, method=0
-i= 1, TAttLine     type=  0, offset= 28, len=1, method=142484480
-i= 2, TAttFill     type=  0, offset= 40, len=1, method=142496992
-i= 3, TAttMarker   type=  0, offset= 48, len=1, method=142509704
-```
-
-For example, the five data members beginning with `fEnties `and the
-three data members beginning with `fMaximum`, are put into an array
-called `fEntries` (`i = 9`) with the length 8.
-
-``` {.cpp}
-i= 9, fEntries     type= 28, offset=452, len=8, method=0
-```
-
-Only simple type data members are combined, object data members are not
-combined. For example the three axis data members remain separate. The
-"method" is a handle to the method that reads the object.
-
-### Automatic Schema Evolution
-
-
-When a class is defined in ROOT, it must include the `ClassDef` macro as
-the last line in the header file inside the class definition. The syntax
-is:
-
-``` {.cpp}
-ClassDef(<ClassName>,<VersionNumber>)
-```
-
-The version number identifies this particular version of the class. When
-a class has version 0 it is not stored in a root file but its base
-class(es) is(are). The reason can be that this class has no data members
-worth saving or all real info is in the base classes. The version number
-is written to the file in the `Streamer` by the call
-`TBuffer::WriteVersion`. You, as the designer of the class, do not need
-to do any manual modification in the `Streamer`. ROOT schema evolution
-mechanism is automatic and handled by the `StreamerInfo`.
-
-### Manual Data Model Evolution Capabilities
-
-   The automatic data model schema evolution implemented in ROOT makes it possible
-to read back the serialized data object in the situation when the definition of
-the classes those objects represent changed slightly (some of the data members were
-removed or some new ones added). It is also possible to manually specify the rules
-for more sophisticated data transformations done while reading to load the serialized
-objects into data structures that changed quite significantly.
-
-   ROOT provides two interface enabling users to specify the conversion rules. The
-first way is to define a rule in the dictionary file and the second way is to insert
-it to the TClass object using the C++ API.
-
-   There are two types of conversion rules. The first of them, the normal rules, are
-the ones that should be used in the most of the cases. They provide a buffered input
-data and an address of the in-memory target object and allow user to specify the
-conversion function mapping the data being read to the output format. The second type
-of the rules, the raw rules, also provide the pointer to the target object but the
-input is a raw TBuffer object containing the input data member declared as an input
-to the rule. This type of a rule is provided mainly to handle the file format changes
-that couldn't have been handled otherwise and in general should not be used unless there
-is no other option.
-
-#### The dictionaries
-
-   The most convenient place to specify the conversion rules is a dictionary. One can
-do that either in a LinkDef file or in the selection xml file being fed to genreflex.
-The syntax of the rules is the following:
-
-   - For dictionaries created from a LinkDef file:
-
-``` {.cpp}
-#pragma read                                              \
-    sourceClass="ClassA"                                  \
-    source="double m_a; double m_b; double m_c"           \
-    version="[4-5,7,9,12-]"                               \
-    checksum="[12345,123456]"                             \
-    targetClass="ClassB"                                  \
-    target="m_x"                                          \
-    embed="true"                                          \
-    include="iostream,cstdlib"                            \
-    code="{m_x = onfile.m_a * onfile.m_b * onfile.m_c; }" \
-
-
-#pragma readraw           \
-      sourceClass="TAxis" \
-      source="fXbins"     \
-      targetClass="TAxis" \
-      target="fXbins"     \
-      version="[-5]"      \
-      include="TAxis.h"   \
-      code="\
-{\
-Float_t * xbins=0; \
-Int_t n = buffer.ReadArray( xbins ); \
-fXbins.Set( xbins ); \
-}"
-```
-
-   - For REFLEX dictionaries:
-
-``` {.cpp}
-<ioread sourceClass="ClassA"
-        source="double m_a; double m_b; double m_c"
-        version="[4-5,7,9,12-]"
-        checksum="[12345,123456]"
-        targetClass="ClassB"
-        target="m_x"
-        embed="true"
-        include="iostream,cstdlib">
-<![CDATA[
-   m_x = onfile.m_a * onfile.m_b * onfile.m_c;
-]] >
-</ioread>
-
-<ioreadraw sourceClass="TAxis"
-           source="fXbins"
-           targetClass="TAxis"
-           target="fXbins"
-           version="[-5]"
-           include="TAxis.h">
-<![CDATA[
-      Float_t *xbins = 0;
-      Int_t n = buffer.ReadArray( xbins ) ;
-      fXbins.Set( xbins );
-]] >
-</ioreadraw>
-```
-
-   The variables in the rules have the following meaning:
-
-  * sourceClass
-     - The field defines the on-disk class that is the input for the rule.
-  * source
-     - A semicolon-separated list of values defining the source class data members
-       that need to be cached and accessible via object proxy when the rule is
-       executed. The values are either the names of the data members or the type-name
-       pairs (separated by a space). If types are specified then the ondisk structure
-       can be generated and used in the code snippet defined by the user.
-  * version
-     - A list of versions of the source class that can be an input for this rule.
-       The list has to be enclosed in a square bracket and be a comma-separated
-       list of versions or version ranges. The version is an integer number, whereas
-       the version range is one of the following:
-      - "a-b": a and b are integers and the expression means all the numbers between
-         and including a and b
-      - "-a": a is an integer and the expression means all the version numbers smaller
-         than or equal to a
-      - "a-": a is an integer and the expression means all the version numbers greater
-        than or equal to a
-  * checksum
-     - A list of checksums of the source class that can be an input for this
-                  rule. The list has to be enclosed in a square brackets and is a
-                  comma-separated list of integers.
-  * targetClass
-     - The field is obligatory and defines the name of the in-memory class that
-       this rule can be applied to.
-  * target
-     - A comma-separated list of target class data member names that this rule
-       is capable of calculating.
-  * embed
-     - This property tells the system if the rule should be written in the output
-       file is some objects of this class are serialized.
-  * include
-     - A list of header files that should be included in order to provide the
-       functionality used in the code snippet; the list is comma delimited.
-  * code
-     - An user specified code snippet
-
-   The user can assume that in the provided code snippet the following variables
-will be defined:
-
-    The user provided code snippets have to consist of valid C++ code. The system can do
-some preprocessing before wrapping the code into function calls and declare some variables to
-facilitate the rule definitions. The user can expect the following variables being predeclared:
-
-   * newObj
-      - variable representing the target in-memory object, its type is that of the
-                  target object
-   * oldObj
-      - in normal conversion rules, an object of TVirtualObject class representing the
-        input data, guaranteed to hold the data members declared in the source property
-        of the rule
-   * buffer
-      - in raw conversion rules, an object of TBuffer class holding the data member
-        declared in source property of the rule
-   * names of the data members of the target object declared in the target property of the
-     rule declared to be the appropriate type
-   * onfile.xxx
-     - in normal conversion rules, names of the variables of basic types declared
-       in the source property of the rule
-
-#### The C++ API
-
-The schema evolution C++ API consists of two classes: `ROOT::TSchemaRuleSet` and
-`ROOT::TSchemaRule`. Objects of the TSchemaRule class represent the rules and their fields have exactly the same
-meaning as the ones of rules specified in the dictionaries. `TSchemaRuleSet` objects
-manage the sets of rules and ensure their consistency. There can be no conflicting
-rules in the rule sets. The rule sets are owned by the `TClass` objects corresponding to the
-target classes defined in the rules and can be accessed using `TClass::{Get|Adopt}SchemaRules`.
-
-### Manual Schema Evolution
-
-
-If you have written your own `Streamer` as described in the section
-"Streamers with Special Additions", you will have to manually add code
-for each version and manage the evolution of your class. When you add or
-remove data members, you must modify the `Streamer` by hand. ROOT
-assumes that you have increased the class version number in the
-`ClassDef` statement and introduced the relevant test in the read part
-of the Streamer. For example, if a new version of the `Event` class
-above includes a new member: `Int_t fNew` the `ClassDef` statement
-should be changed to `ClassDef(Event,2)` and the following lines should
-be added to the read part of the `Streamer`:
-
-``` {.cpp}
-   if (R__v > 1) R__b >> fNew;
-   else fNew = 0;        // set to some default value
-```
-
-If, in the same new version 2 you remove the member `fH`, you must add
-the following code to read the histogram object into some temporary
-object and delete it:
-
-``` {.cpp}
-if (R__v) < 2 {
-   TH1F *dummy = 0;
-   R__b >> dummy;
-   delete dummy;
-}
-```
-
-Our experience with manual schema evolution shows that it is easy to
-make and mismatches between `Streamer` writers and readers are frequent
-and increase as the number of classes increase. We recommend you use
-`rootcling` generated `Streamers` whenever you can, and profit from the
-automatic schema evolution.
-
-### Building Class Definitions with the StreamerInfo
-
-
-A ROOT file's `StreamerInfo `list contains the description of all
-versions of all classes in the file. When a file is opened the
-`StreamerInfo `is read into memory and it provides enough information to
-make the file browsable. The `TStreamerInfo `enables us to recreate a
-header file for the class in case the compiled class is not available.
-This is done with the `TFile::MakeProject` method. It creates a
-directory with the header files for the named classes and a `makefile`
-to compile a shared library with the class definitions.
-
-### Example: MakeProject
-
-
-To explain the details, we use the example of the `ATLFast` project that
-is a fast simulation for the ATLAS experiment. The complete source for
-`ATLFast` can be down loaded at
-<ftp://root.cern.ch/root/atlfast.tar.gz>. Once we compile and run
-`ATLFast` we get a ROOT file called `atlfast.root`, containing the
-`ATLFast` objects. When we open the file, we get a warning that the file
-contains classes that are not in the dictionary. This is correct
-since we did not load the class definitions.
-
-``` {.cpp}
-root[] TFile f("atlfast.root")
-Warning in <TClass::TClass>: no dictionary for class TMCParticle is available
-Warning in <TClass::TClass>: no dictionary for class ATLFMuon available
-```
-
-We can see the `StreamerInfo `for the classes:
-
-``` {.cpp}
-root[] f.ShowStreamerInfo()
-...
-StreamerInfo for class: ATLFMuon, version=1
-BASE  TObject      offset=  0 type=66 Basic ROOT object
-BASE  TAtt3D       offset=  0 type= 0 3D attributes
-Int_t m_KFcode     offset=  0 type= 3 Muon KF-code
-Int_t m_MCParticle offset=  0 type= 3 Muon position in MCParticles list
-Int_t m_KFmother   offset=  0 type= 3 Muon mother KF-code
-Int_t m_UseFlag    offset=  0 type= 3 Muon energy usage flag
-Int_t m_Isolated   offset=  0 type= 3 Muon isolation (1 for isolated)
-Float_t m_Eta      offset=  0 type= 5 Eta coordinate
-Float_t m_Phi      offset=  0 type= 5 Phi coordinate
-Float_t m_PT       offset=  0 type= 5 Transverse energy
-Int_t   m_Trigger  offset=  0 type= 3 Result of trigger...
-```
-
-However, when we try to use a specific class we get a warning because
-the class is not in the dictionary. We can create a class using
-`gROOT->GetClass()` which makes a fake class from the `StreamerInfo`.
-
-``` {.cpp}
-// Build a 'fake' class
-root[] gROOT->GetClass("ATLFMuon")
-(const class TClass*)0x87e5c08
-// The fake class has a StreamerInfo
-root[] gROOT->GetClass("ATLFMuon")->GetStreamerInfo()->ls()
-StreamerInfo for class: ATLFMuon, version=1
-  BASE    TObject       offset=  0 type=66 Basic ROOT object
-  BASE    TAtt3D        offset=  0 type= 0 3D attributes
-  Int_t   m_KFcode      offset= 16 type= 3 Muon KF-code
-  Int_t   m_MCParticle  offset= 20 type= 3 Muon position in MCParticles list
-  Int_t   m_KFmother    offset= 24 type= 3 Muon mother KF-code
-  Int_t   m_UseFlag     offset= 28 type= 3 Muon energy usage flag
-  Int_t   m_Isolated    offset= 32 type= 3 Muon isolation
-  Float_t m_Eta         offset= 36 type= 5 Eta coordinate
-  Float_t m_Phi         offset= 40 type= 5 Phi coordinate
-  Float_t m_PT          offset= 44 type= 5 Transverse energy
-  Int_t   m_Trigger     offset= 48 type= 3 Result of trigger
-  i= 0, TObject         type= 66, offset=  0, len=1, method=0
-  i= 1, TAtt3D          type=  0, offset=  0, len=1, method=142684688
-  i= 2, m_KFcode        type= 23, offset= 16, len=5, method=0
-  i= 3, m_Eta           type= 25, offset= 36, len=3, method=0
-  i= 4, m_Trigger       type=  3, offset= 48, len=1, method=0
-```
-
-`MakeProject` has three parameters:
-
-``` {.cpp}
-MakeProject(const char *dirname,const char *classes,Option_t *option)
-```
-
-The first is the directory name in which to place the generated header
-files. The second parameter is the name of the classes to include in the
-project. By default, all classes are included. It recognizes the wild
-card character \*, for example, "ATLF\*" includes all classes beginning
-with ATLF. The third parameter is an option with the following values:
-
--   "`new`" If the directory does not exist, it is created.
-
--   "`recreate`" If the directory does not exist, it is creates as in
-    "new", in addition if the directory does exist, all existing files
-    are deleted before creating the new files.
-
--   "`update`" The new classes are added to the existing directory and
-    the existing classes are replaced with the new definition. If the
-    directory does not exist, it creates it as in "new".
-
--   "+": This option can be used in combination with the other three. It
-    will create the necessary files to easily build a shared library
-    containing the class definitions.Specifically it will:
-
--   Generate a script called `MAKE` that builds the shared library
-    containing the definition of all classes in the directory.
-
--   Generate a `LinkDef.h `files to use with `rootcling` in `MAKE`.
-
--   Run `rootcling` to generate a `<dirname>ProjectDict.cxx` file.
-
--   Compile the \<`dirname>ProjectDict.cxx `with the current options in
-    `compiledata.h`.
-
--   Build a shared library` <dirname>.so`.
-
--   "++":This option can be used instead of the single "+". It does
-    everything the single "+" does, and dynamically loads the shared
-    library `<dirname>.so`.
-
-This example makes a directory called `MyProject` that will contain all
-class definitions from the `atlfast.root` file. The necessary `makefile`
-to build a shared library are also created, and since the '++' is
-appended, the shared library is also loaded.
-
-``` {.cpp}
-root[] f.MakeProject("MyProject","*", "recreate++")
-MakeProject has generated 0 classes in MyProject
-MyProject/MAKE file has been generated
-Shared lib MyProject/MyProject.so has been generated
-Shared lib MyProject/MyProject.so has been dynamically linked
-```
-
-The contents of `MyProject`:
-
-``` {.cpp}
-root[]     .! ls MyProject
-ATLFCluster.h      ATLFJet.h           ATLFMiscMaker.h     ATLFTrack.h
-TMCParticle.h      ATLFClusterMaker.h  ATLFJetMaker.h      ATLFMuon.h
-ATLFElectron.h     ATLFMCMaker.h       ATLFMuonMaker.h     ATLFElectronMaker.h
-ATLFMaker.h        ATLFPhoton.h        ATLFHistBrowser.h   ATLFMisc.h
-ATLFPhotonMaker.h  ATLFTrackMaker.h    ATLFTrigger.h       ATLFTriggerMaker.h
-LinkDef.h          MAKE                MyProject.so        MyProjectProjectDict.h
-MyProjectProjectDict.cxx               MyProjectProjectDict.o
-```
-
-Now you can load the shared library in any consecutive root session to
-use the `atlfast` classes.
-
-``` {.cpp}
-root[]gSystem->Load("MyProject/MyProject")
-root[]ATLFMuon muon
-```
-
-This is an example of a generated header file:
-
-``` {.cpp}
-//////////////////////////////////////////////////////////
-//   This class has been generated by TFile::MakeProject
-//     (Thu Apr  5 10:18:37 2001 by ROOT version 3.00/06)
-//      from the TStreamerInfo in file atlfast.root
-//////////////////////////////////////////////////////////
-#ifndef ATLFMuon_h
-#define ATLFMuon_h
-#include "TObject.h"
-#include "TAtt3D.h"
-class ATLFMuon : public TObject , public TAtt3D {
-public:
-   Int_t     m_KFcode;           //Muon KF-code
-   Int_t     m_MCParticle;       //Muon position in MCParticles list
-   Int_t     m_KFmother;         //Muon mother KF-code
-   Int_t     m_UseFlag;          //Muon energy usage flag
-   Int_t     m_Isolated;         //Muon isolation (1 for isolated)
-   Float_t   m_Eta;              //Eta coordinate
-   Float_t   m_Phi;              //Phi coordinate
-   Float_t   m_PT;               //Transverse energy
-   Int_t     m_Trigger;          //Result of trigger
-   ATLFMuon() {;}
-   virtual ~ATLFMuon() {;}
-   ClassDef(ATLFMuon,1) //
-};
-   ClassImp(ATLFMuon)
-#endif
-```
-
-## Compression and Performance
-
-
-ROOT uses a compression algorithm based on the well-known `gzip`
-algorithm. It supports nine levels of compression. The default for ROOT
-is one. The compression level can be set with the method
-`TFile::SetCompressionLevel`. The experience with this algorithm shows
-that a compression level of 1.3 for raw data files and around two on
-most DST files is the optimum. The choice of one for the default is a
-compromise between the time it takes to read and write the object vs.
-the disk space savings.
-
-To specify no compression, set the level to zero.
-
-We recommend using compression when the time spent in I/O is small
-compared to the total processing time. If the I/O operation is increased
-by a factor of 5 it is still a small percentage of the total time and it
-may compress the data by a factor of 10. On the other hand if the time
-spend on I/O is large, compression may have a large impact on the
-program's performance.
-
-The compression factor, i.e. the savings of disk space, varies with the
-type of data. A buffer with a same value array is compressed so that the
-value is only written once. For example, a track has the mass of a pion
-that it is always the same, and the charge of the pion that is either
-positive or negative. For 1000 pions, the mass will be written only
-once, and the charge only twice (positive and negative). When the data
-is sparse, i.e. when there are many zeros, the compression factor is
-also high.
-
-+---------------------+------------------+-------------------+-------------------+
-| Compression level   | Bytes            | Write Time (sec)  | Read Time (sec.)  |
-+---------------------+------------------+-------------------+-------------------+
-| 0                   | 1,004,998        | 4.77              | 0.07              |
-+---------------------+------------------+-------------------+-------------------+
-| 1                   | 438,366          | 6.67              | 0.05              |
-+---------------------+------------------+-------------------+-------------------+
-| 5                   | 429,871          | 7.03              | 0.06              |
-+---------------------+------------------+-------------------+-------------------+
-| 9                   | 426,899          | 8.47              | 0.05              |
-+---------------------+------------------+-------------------+-------------------+
-
-The time to uncompress an object is small compared to the compression
-time and is independent of the selected compression level. Note that the
-compression level may be changed at any time, but the new compression
-level will only apply to newly written objects. Consequently, a ROOT
-file may contain objects with different compression levels. This table
-shows four runs of the demo script that creates 15 histograms with
-different compression parameters. To make the numbers more significant,
-the macro was modified to create 1000 histograms. We have included two
-more examples to show the impact of compression on Trees in the next
-chapter.
-
-### Using the General Open Function of TFile
-
-
-To make life simple we provide a general function to open any type of
-file (except shared memory files of class **`TMapFile`**). This
-functionality is provided by the static `TFile::Open()` function:
-
-``` {.cpp}
-TFile *TFile::Open(const Text_t *name,Option_t *option="",
-const Text_t *title="",Int_t compress,Int_t netopt)
-```
-
-Depending on the `name` argument, the function returns a **`TFile`** or one
-of its derivations, for example a
-**`TNetXNGFile`** or a **`TDavixFile`** object. In case a URL
-specifies a local file, a **`TFile`** object will be returned (and of
-course no login information is needed). The arguments of the `Open()`
-function are the same as the ones for the **`TFile`** constructor.
-
-Using `ReOpen()` method it is possible to reopen a file with a
-different access mode, like from READ to UPDATE or from NEW, CREATE,
-RECREATE, UPDATE to READ. Thus the mode argument can be either "READ" or
-"UPDATE". The method returns:
-
--   0 in case the mode was successfully modified;
-
--   1 in case the mode did not change (it was already as requested or
-    there were wrong input arguments);
-
--   -1 in case of failure. In the last case the file cannot be used
-    anymore.
-
-
-## Remotely Access to ROOT Files
-
-ROOT files can be accessed remotely in many ways, on the base of the protocol
-URL. Among the most popular are XRootD (protocols 'root://' and 'xrd://') and
-a Web server (protocl 'http://' or 'https://').
-
-The rootd daemon is deprecated and has been removed in version 6.16/00.
-
-Please refer to the XRootD documentation for starting and ensuring that such a
-daemon is running.
-
-Reading and writing ROOT files over the net can be done by creating a
-**`TFile`** object using the static method **`TFile::Open()`** object.
-This will instantiate the appropriate derivation of **`TFile`** to handle the
-request. Inheriting from the **`TFile`** class, the returned instance will have
-exactly the same interface and behavior of **`TFile`**. The only difference
-is that it reads and writes from a remote service.
-In the example below the file is read via a web server through the TDavixFile plug-in.
-
-
-### A Simple Session
-
-
-``` {.cpp}
-root[] TFile *f1 = TFile::Open("local/file.root","update")
-root[] TFile *f2 = TFile::Open("root://my.server.org/data/file.root","new")
-root[] TFile *f3 = TFile::Open("http://root.cern.ch/files/hsimple.root")
-root[] f3.ls()
-TDavixFile** http://root.cern.ch/files/hsimple.root
-TDavixFile* http://root.cern.ch/files/hsimple.root
-KEY: TH1F hpx;1 This is the px distribution
-KEY: TH2F hpxpy;1 py vs px
-KEY: TProfile hprof;1 Profile of pz versus px
-KEY: TNtuple ntuple;1 Demo ntuple
-root[] hpx.Draw()
-```
-
-## XML Interface
-
-
-A new module `xml` as implemented by Sergey Linev (GSI). It is an
-optional package that can be used to save a canvas into `file.xml` file
-format instead of `file.root`. XML files do not have any advantages
-compared to the normal ROOT files, except that the information in these
-files can be edited via a normal editor. The main motivation for this
-new format is to facilitate the communication with other non ROOT
-applications. Currently writing and reading XML files is limited to ROOT
-applications. It is our intention to develop a simple reader independent
-of the ROOT libraries that could be used as an example for real
-applications.
-
-The XML format should be used only for small data volumes, typically
-histogram files, pictures, geometries, calibrations. The XML file is
-built in memory before being dumped to disk. Like for normal ROOT files,
-XML files use the same I/O mechanism exploiting the ROOT/Cling
-dictionary. Any class having a dictionary can be saved in XML format.
-This first implementation does not support subdirectories or trees.
-
-The shared library `libRXML.so` may be loaded dynamically via
-`gSystem->Load("libRXML")`. This library is also automatically loaded by
-the plug-in manager as soon a XML file is created. To create an XTM
-file, simply specify a filename with an .xml extension when calling
-**`TFile`**`::Open`. **`TFile`**`::Open` will recognize that you are trying to
-open an XML file and return a **`TXMLFile`** object. When a XML file is
-open in write mode, one can use the normal `TObject::Write` to write an
-object in the file.
-
-``` {.cpp}
-   // example of a session saving a histogram to a XML file
-   TFile *f = TFile::Open("Example.xml","recreate");
-   TH1F *h = new TH1F("h","test",1000,-2,2)
-   h->FillRandom("gaus");
-   h->Write();
-   delete f;
-   // example of a session saving a histogram to a XML file
-   TFile *f = TFile::Open("Example.xml");
-   TH1F *h = (TH1F*)f->Get("h");
-   h->Draw();
-```
-
-The canvas can be saved as a XML file format via File menu / Save or
-Save As menu entries. One can do also:
-
-``` {.cpp}
-   canvas->Print("Example.xml");
-```
diff --git a/documentation/users-guide/InstallandBuild.md b/documentation/users-guide/InstallandBuild.md
deleted file mode 100644
index 7e7c9e14a376a..0000000000000
--- a/documentation/users-guide/InstallandBuild.md
+++ /dev/null
@@ -1,592 +0,0 @@
-# Appendix A: Install and Build ROOT
-\index{install ROOT}
-
-## License
-
-
-ROOT is made available under the LGPL v2.1 license. For full details see
-the file LICENSE in the ROOT distribution.
-
-## Installing ROOT
-
-
-To install ROOT you will need to go to the ROOT website at:
-<https://root.cern/install/>
-
-You have a choice to download the binaries or the source. The source is
-quicker to transfer since it is only 31 MB, but you will need to compile
-and link it. The binaries range from 50 MB to 100 MB depending on the
-target platform.
-
-## Choosing a Version
-
-
-The ROOT developers follow the principle of "release early and release
-often", however a very large portion of a user base requires a stable
-product therefore generally three versions of the system is available
-for download - new, old and pro:
-
--   The *new* version evolves quickly, with weekly or bi-weekly
-    releases. Use this to get access to the latest and greatest, but it
-    may not be stable. By trying out the new version you can help us
-    converge quickly to a stable version that can then become the new
-    pro version. If you are a new user we would advice you to try the
-    new version.
-
--   The *pro* (production) version is a version we feel comfortable with
-    to exposing to a large audience for serious work. The change rate of
-    this version is much lower than for the new version, it is about 3
-    to 6 months.
-
--   The *old* version is the previous pro version that people might need
-    for some time before switching the new pro version. The old change
-    rate is the same as for pro.
-
-## Installing Precompiled Binaries
-
-
-The binaries are available for downloading from
-<https://root.cern/install/>. Once downloaded
-you need to unzip and de-tar the file. For example, if you have
-downloaded ROOT v5.30 for Linux-SLC5:
-
-``` {.cpp}
-% gunzip root_v5.30.00.Linux-slc5-gcc4.3.tar.gz
-% tar xvf root_v5.30.00.Linux-slc5-gcc4.3.tar
-```
-
-This will create the directory root. Before getting started read the
-file README/README. Also, read the Introduction chapter for an
-explanation of the directory structure.
-
-## Installing from the Source
-
-The ROOT's source code sits in the GitHub repository <https://github.com/root-project/root>
-all the details and options to buld ROOT from sources are given in
-<https://root.cern/building-root>
-
-In short, the steps to build ROOT from the sources are the following:
-
-  1. Clone the repository:
-``` {.cpp}
-$ git clone https://github.com/root-project/root.git
-```
-
-  2. Make a directory for building
-``` {.cpp}
-$ mkdir build
-$ cd build
-```
-
-  3. Run cmake and make
-``` {.cpp}
-$ cmake ../root
-$ make -j8
-```
-
-  4. Setup and run ROOT
-``` {.cpp}
-$ source bin/thisroot.sh
-$ root
-```
-
-#### Staying up-to-date
-
-To keep your local ROOT source up-to-date with the GitHub repository
-you should regularly run the command:
-
-``` {.cpp}
-% git pull
-```
-
-## File system.rootrc
-
-
-ROOT Environment settings are handled via the class **`TEnv`**.
-`gEnv->Print()`shows which values are active. Any settings can be
-obtained by `TEnv::GetValue` methods that return an integer, double or
-character value for a named resource. If the resource is not found, the
-default value (given as the second parameter) is returned.
-
-``` {.cpp}
-fShowEventStatus = gEnv->GetValue("Canvas.ShowEventStatus",kFALSE);
-```
-
-Via the method `TEnv::SetValue` allows you can set the value of a
-resource or create a new resource:
-
-``` {.cpp}
-gEnv->SetValue("Root.ObjectStat",1);
-```
-
-Path used by dynamic loader to find shared libraries and macros. Paths
-are different for Unix and Windows. The example shows the defaults for
-all ROOT applications for either Unix or Windows:
-
-``` {.cpp}
-Unix.*.Root.DynamicPath:    .:$(ROOTSYS)/lib
-Unix.*.Root.MacroPath:      .:$(ROOTSYS)/macros
-WinNT.*.Root.DynamicPath:   .;$(ROOTSYS)/bin;$(PATH)
-WinNT.*.Root.MacroPath:     .;$(ROOTSYS)/macros
-```
-
-Path where to look for `TrueType` fonts:
-
-``` {.cpp}
-Unix.*.Root.UseTTFonts:     true
-*.*.Root.TTFontPath:        $(ROOTSYS)/fonts
-```
-
-Use `Net* API` functions:
-
-``` {.cpp}
-WinNT.UseNetAPI:            true
-```
-
-Use thread library (if exists).
-
-``` {.cpp}
-Unix.*.Root.UseThreads:     false
-```
-
-Select the compression algorithm (0=old zlib, 1=new zlib). Setting this
-to \`0' may be a security vulnerability.
-
-``` {.cpp}
-Root.ZipMode:               1
-```
-
-Show where item is found in the specified path:
-
-``` {.cpp}
-Root.ShowPath:              false
-```
-
-Activate memory statistics.
-
-``` {.cpp}
-Root.ObjectStat:            0
-```
-
-Global debug mode. When `>0` turns on progressively more details
-debugging.
-
-``` {.cpp}
-Root.Debug:                 0
-Root.Stacktrace:            yes
-```
-
-Settings for X11 behaviour.
-
-``` {.cpp}
-X11.Sync:                   no
-X11.FindBestVisual:         yes
-```
-
-Default editor in use.
-
-``` {.cpp}
-Unix.*.Editor:              vi
-WinNT.*.Editor:             notepad
-```
-
-Default 3d Viewer. By default 3-D views are shown in the pad, if the
-next line is activated, the default viewer will be OpenGL.
-
-``` {.cpp}
-Viewer3D.DefaultDrawOption: ogl
-```
-
-Default Fitter (current choices are `Minuit`, `Minuit2`, `Fumili` and
-`Fumili2`).
-
-``` {.cpp}
-Root.Fitter:                Minuit
-```
-
-Specify list of file endings which **`TTabCom`** (TAB completion) should
-ignore.
-
-``` {.cpp}
-TabCom.FileIgnore:          .cpp:.h:.cmz
-```
-
-### TCanvas Specific Settings
-
-
-Opaque move and resize show full pad during the operation instead of
-only the outline. Especially for resize you will need serious CPU power.
-`UseScreenFactor=true` means to size canvas according to size of screen,
-so a canvas still looks good on a low resolution laptop screen without
-having to change canvas size in macros.
-
-``` {.cpp}
-Canvas.MoveOpaque:          false
-Canvas.ResizeOpaque:        false
-Canvas.UseScreenFactor:     true
-```
-
-Hight color 2 is the red one.
-
-``` {.cpp}
-Canvas.HighLightColor:      2
-```
-
-Next three settings are related to different user interface parts of
-canvas window. If they are set to true, the corresponding event status
-bar, tool bar, graphics editor will be activated by default.
-
-``` {.cpp}
-Canvas.ShowEventStatus:     false
-Canvas.ShowToolBar:         false
-Canvas.ShowEditor:          false
-```
-
-AutoExec allows **`TExec`** objects to be executed on mouse and key
-events.
-
-``` {.cpp}
-Canvas.AutoExec:            true
-```
-
-Canvas print directory is set to the current one by default:
-
-``` {.cpp}
-Canvas.PrintDirectory     .
-```
-
-Printer settings:
-
-``` {.cpp}
-WinNT.*.Print.Command:    AcroRd32.exe
-#Unix.*.Print.Command:    a2ps -P%p --landscape --columns=2 --margin=30 -rf8.0 %f
-Print.Printer:            32-rb20-hp
-Print.Directory:          .
-Print.FileType:           pdf
-```
-
-Default histogram binnings used by `TTree::Draw()` method.
-
-``` {.cpp}
-Hist.Binning.1D.x:          100
-Hist.Binning.2D.x:           40
-Hist.Binning.2D.y:           40
-Hist.Binning.2D.Prof:       100
-Hist.Binning.3D.x:           20
-Hist.Binning.3D.y:           20
-Hist.Binning.3D.z:           20
-Hist.Binning.3D.Profx:      100
-Hist.Binning.3D.Profy:      100
-```
-
-Default statistics names used for parameters in **`TPaveStats`**:
-
-``` {.cpp}
-Hist.Stats.Entries         Entries
-Hist.Stats.Mean            Mean
-Hist.Stats.MeanX           Mean x
-Hist.Stats.MeanY           Mean y
-Hist.Stats.RMS             RMS
-Hist.Stats.RMSX            RMS x
-Hist.Stats.RMSY            RMS y
-Hist.Stats.Underflow       Underflow
-Hist.Stats.Overflow        Overflow
-Hist.Stats.Integral        Integral
-Hist.Stats.Skewness        Skewness
-Hist.Stats.SkewnessX       Skewness x
-Hist.Stats.SkewnessY       Skewness y
-Hist.Stats.Kurtosis        Kurtosis
-Hist.Stats.KurtosisX       Kurtosis x
-Hist.Stats.KurtosisY       Kurtosis y
-```
-
-### THtml Specific Settings
-
-
-See the reference guide documentation of **`THtml`** class at
-<https://root.cern/doc/master/classTHtml.html> for more details.
-
-XHTML content charset (see
-<http://www.w3.org/TR/2002/REC-xhtml1-20020801>, default: ISO-8859-1) is
-set by:
-
-``` {.cpp}
-Root.Html.Charset:
-```
-
-Stem of a search engine for the documentation, where `%s` is replaced by
-the term entered in the search text box (example:
-`http://www.google.com/search?q=%s+site%3Aroot.cern.ch%2Froot%2Fhtml`,
-default is `""`)
-
-``` {.cpp}
-Root.Html.Search:
-```
-
-Link to the site's search engine (default: `""`, example:
-`http://root.cern.ch/root/Search.phtml`)
-
-``` {.cpp}
-Root.Html.SearchEngine:
-```
-
-String to prepend to `TClass::GetImplFileName()` names containing
-directories when looking for source files (default: `""`, `e`xample:
-`../root`)
-
-``` {.cpp}
-Root.Html.SourcePrefix:
-```
-
-Link stem to `ViewCVS` entry for classes, where a class name is assumed
-to match a file name (default: `""`, example:
-`http://root.cern.ch/viewcvs`).
-
-``` {.cpp}
-Root.Html.ViewCVS:
-```
-
-Stem of the CERN XWho system (default:
-`http://consult.cern.ch/xwho/people?`)
-
-``` {.cpp}
-Root.Html.XWho:
-```
-
-If set to Doc++, allow method documentation in front of method even for
-methods in the source file (default: `""`)
-
-``` {.cpp}
-Root.Html.DescriptionStyle:
-```
-
-Search path for the source and header files with their default settings:
-
-``` {.cpp}
-Unix.*.Root.Html.SourceDir:  .:src:include
-WinNT.*.Root.Html.SourceDir: .;src;include
-```
-
-URL stem for ROOT documentation pages (default is `""`).
-
-``` {.cpp}
-Root.Html.Root:              http://root.cern.ch/root/html
-```
-
-Filesystem output directory for generated web pages (default:
-`htmldoc)`.
-
-``` {.cpp}
-Root.Html.OutputDir:        htmldoc/
-```
-
-Address of the package's home page (default: <http://root.cern.ch>):
-
-``` {.cpp}
-Root.Html.HomePage:
-```
-
-Location of user defined header and footer files, see
-<http://root.cern.ch/root/html/THtml#conf:header> (defaults are `""`,
-example: `../header.txt`, `../footer.txt`):
-
-``` {.cpp}
-Root.Html.Header:
-Root.Html.Footer:
-```
-
-Tag for detecting class description comments (default value is set
-below).
-
-``` {.cpp}
-Root.Html.Description:      //____________________
-```
-
-Tag for detecting "Author" comment (default value is set below).
-
-``` {.cpp}
-Root.Html.Author:           // Author:
-```
-
-Tag for detecting "last updated" comment. **`THtml`** uses the current
-date if this tag is not found in a class source file (default value is
-set below).
-
-``` {.cpp}
-Root.Html.LastUpdate:       // @(#)
-```
-
-Tag for detecting "Copyright" comment (default value is set below).
-
-``` {.cpp}
-Root.Html.Copyright:        * Copyright
-```
-
-### GUI Specific Settings
-
-
-Set the "`native`" ROOT GUI interface to be used in a ROOT session.
-
-``` {.cpp}
-Gui.Backend:                native
-Gui.Factory:                native
-```
-
-GUI default fonts in use:
-
-``` {.cpp}
-Gui.DefaultFont:            -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-1
-Gui.MenuFont:               -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-1
-Gui.MenuHiFont:             -adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1
-Gui.DocFixedFont:           -adobe-courier-medium-r-*-*-12-*-*-*-*-*-iso8859-1
-Gui.DocPropFont:            -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-1
-Gui.IconFont:               -adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1
-Gui.StatusFont:             -adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1
-```
-
-Regular background and foreground colors in use:
-
-``` {.cpp}
-Gui.BackgroundColor:         #c0c0c0
-Gui.ForegroundColor:         black
-```
-
-Selection background and foreground colors in use:
-
-``` {.cpp}
-Gui.SelectBackgroundColor:   #000080
-Gui.SelectForegroundColor:   white
-```
-
-Document background and foreground colors in use:
-
-``` {.cpp}
-Gui.DocumentBackgroundColor: white
-Gui.DocumentForegroundColor: black
-```
-
-Tooltip background and foreground colors in use:
-
-``` {.cpp}
-Gui.TooltipBackgroundColor:  LightYellow
-Gui.TooltipForegroundColor:  black
-```
-
-Path where all GUI icons in use can be found:
-
-``` {.cpp}
-Gui.IconPath:                $(HOME)/icons:$(ROOTSYS)/icons:.
-```
-
-Mime type file setting:
-
-``` {.cpp}
-Gui.MimeTypeFile:            $(HOME)/.root.mimes
-```
-
-If `$(HOME)/.root.mimes` does not exists, defaults to this:
-
-``` {.cpp}
-#Gui.MimeTypeFile:            $(ROOTSYS)/etc/root.mimes
-```
-
-### TBrowser Settings
-
-
-Current icon style selection - can be either `small`, `big`, `list`,
-`details`:
-
-``` {.cpp}
-Browser.IconStyle:           small
-```
-
-Current sorting rule applied on the browser objects - can be `name`,
-`type`, `size`, `date`:
-
-``` {.cpp}
-Browser.SortBy:              name
-```
-
-Number of items in a group view:
-
-``` {.cpp}
-Browser.GroupView:           10000
-```
-
-Show or not hidden items:
-
-``` {.cpp}
-Browser.ShowHidden:          no
-```
-
-Create a thumbnail view after executing the macro (default is `yes`).
-
-``` {.cpp}
-Browser.AutoThumbnail:       yes
-```
-
-### TRint Specific Settings
-
-
-Rint (interactive ROOT executable) specific alias, logon and logoff
-macros.
-
-``` {.cpp}
-Rint.Load:               rootalias.C
-Rint.Logon:              rootlogon.C
-Rint.Logoff:             rootlogoff.C
-```
-
-Record ROOT session commands in a given history file (default is
-`$(HOME)/.root_hist`). If set to "`-`", it turn off the command
-recording.
-
-``` {.cpp}
-Rint.History:            $(HOME)/.root_hist
-```
-
-Next two lines set the history file size handling. Once `HistSize` is
-reached, the last `HistSave` entries are removed. If `HistSize` is set
-to 0, it turns off command recording. Both values can be overridden by
-environment variable `ROOT_HIST=size[:save]`, where the "`:save`" part
-is optional.
-
-``` {.cpp}
-Rint.HistSize:         500
-Rint.HistSave:         400
-```
-
-### ACLiC Specific Settings
-
-
-`ACLiC.Linkdef` specifies the suffix that will be added to the script
-name to try to locate a custom linkdef file when generating the
-dictionary.
-
-``` {.cpp}
-ACLiC.Linkdef:          _linkdef
-```
-
-The top directory for storing the libraries produced by ACLiC is set by:
-
-``` {.cpp}
-ACLiC.BuildDir:        /where/I/would/like/my/compiled/scripts
-```
-
-The additional include directives for ACLiC compilations are set by:
-
-``` {.cpp}
-ACLiC.IncludePaths:     -I/where/the/includes/are
-```
-
-## Documentation to Download
-
-
--   The latest ROOT Users Guide
-
--   <https://root.cern.ch/root/htmldoc/guides/users-guide/ROOTUsersGuide.html>
-
--   ROOT Reference Guide
-
--   <http://root.cern.ch/root/Reference.html>
-
diff --git a/documentation/users-guide/Introduction.md b/documentation/users-guide/Introduction.md
deleted file mode 100644
index d904fb0b9c0b2..0000000000000
--- a/documentation/users-guide/Introduction.md
+++ /dev/null
@@ -1,629 +0,0 @@
-# Introduction
-
-In the mid 1990's, René Brun and Fons Rademakers had many years of
-experience developing interactive tools and simulation packages. They
-had lead successful projects such as PAW, PIAF, and GEANT, and they
-knew PAW the twenty-year-old FORTRAN libraries had reached their
-limits. Although still very popular, these tools could not scale up to
-the challenges offered by the Large Hadron Collider, where the data is
-a few orders of magnitude larger than anything seen before.
-
-At the same time, computer science had made leaps of progress
-especially in the area of Object Oriented Design, and René and Fons
-were ready to take advantage of it.
-
-ROOT was developed in the context of the NA49 experiment at CERN. NA49
-has generated an impressive amount of data, around 10 Terabytes per
-run. This rate provided the ideal environment to develop and test the
-next generation data analysis.
-
-ROOT was, and still is, developed in the "Bazaar style", a term from
-the book "The Cathedral and the Bazaar" by Eric S. Raymond. It means a
-liberal, informal development style that heavily relies on the diverse
-and deep talent of the user community. The result is that physicists
-developed ROOT for themselves; this made it specific, appropriate,
-useful, and over time refined and very powerful. The development of
-ROOT is a continuous conversation between users and developers with
-the line between the two blurring at times and the users becoming
-co-developers.
-
-When it comes to storing and mining large amount of data, physics
-plows the way with its Terabytes, but other fields and industry follow
-close behind as they acquiring more and more data over time. They are
-ready to use the true and tested technologies physics has invented. In
-this way, other fields and industries have found ROOT useful and they
-have started to use it also.
-
-In the bazaar view, software is released early and frequently to
-expose it to thousands of eager co-developers to pound on, report
-bugs, and contribute possible fixes. More users find more bugs,
-because they stress the program in different ways. By now, after ten
-years, the age of ROOT is quite mature. Most likely, you will find the
-features you are looking for, and if you have found a hole, you are
-encouraged to participate in the dialog and post your suggestion or
-even implementation on the ROOT forum.
-
-## The ROOT forum
-
-If you have a question, it is likely that it has been asked, answered,
-and stored in the ROOT Forum. Please use
-the search engine to see if your question has already been answered
-before posting a topic in the
-Forum.
-
-You can access the ROOT forum at: <https://root-forum.cern.ch>.
-
-## Contact Information
-
-
-Several authors wrote this book and you may see a "change of voice"
-from one chapter to the next. We felt we could accept this in order to
-have the expert explain what they know best. If you would like to
-contribute a chapter or add to a section, please contact
-<rootdoc@cern.ch>. We count on you to send us suggestions on
-additional topics or on the topics that need more documentation.
-Please send your comments, corrections, questions, and suggestions to
-the `rootdoc` list: <rootdoc@cern.ch>
-
-We attempt to give the user insight into the many capabilities of
-ROOT. The book begins with the elementary functionality and progresses
-in complexity reaching the specialized topics at the end. The
-experienced user looking for special topics may find these chapters
-useful: see "Networking", "Writing a Graphical User Interface",
-"Threads", and "PROOF: Parallel Processing".
-
-## Conventions Used in This Book
-
-
-We tried to follow a style convention for the sake of clarity. The
-styles in used are described below.
-
-To show source code in scripts or source files:
-
-``` {.cpp}
-{
-   cout << " Hello" << endl;
-   float x = 3.;
-   float y = 5.;
-   int   i = 101;
-   cout <<" x = "<<x<<" y = "<<y<<" i = "<<i<< endl;
-}
-```
-
-To show the ROOT command line, we show the ROOT prompt without numbers.
-In the interactive system, the ROOT prompt has a line number
-(`root[12]`); for the sake of simplicity, the line numbers are left
-off.
-
-``` {.cpp}
-root[] TLine l
-root[] l.Print()
-TLine  X1=0.000000 Y1=0.000000 X2=0.000000 Y2=0.000000
-```
-
-Italic bold monotype font indicates a global variable, for example
-***`gDirectory`***.
-
-When a variable term is used, it is shown between angled brackets. In
-the example below the variable term \<library\> can be replaced with
-any library in the `$ROOTSYS` directory: `$ROOTSYS/<library>/inc.`
-
-## The Framework
-
-
-ROOT is an object-oriented framework aimed at solving the data
-analysis challenges of high-energy physics. There are two key words in
-this definition, object oriented and framework. First, we explain what
-we mean by a framework and then why it is an object-oriented
-framework.
-
-### What Is a Framework?
-
-
-Programming inside a framework is a little like living in a city.
-Plumbing, electricity, telephone, and transportation are services
-provided by the city. In your house, you have interfaces to the
-services such as light switches, electrical outlets, and telephones.
-The details, for example, the routing algorithm of the phone switching
-system, are transparent to you as the user. You do not care; you are
-only interested in using the phone to communicate with your
-collaborators to solve your domain specific problems.
-
-Programming outside of a framework may be compared to living in the
-country. In order to have transportation and water, you will have to
-build a road and dig a well. To have services like telephone and
-electricity you will need to route the wires to your home. In
-addition, you cannot build some things yourself. For example, you
-cannot build a commercial airport on your patch of land. From a global
-perspective, it would make no sense for everyone to build their
-own airport. You see you will be very busy building the infrastructure
-(or framework) before you can use the phone to communicate with your
-collaborators and have a drink of water at the same time. In software
-engineering, it is much the same way. In a framework, the basic
-utilities and services, such as I/O and graphics, are provided. In
-addition, ROOT being a HEP analysis framework, it provides a large
-selection of HEP specific utilities such as histograms and fitting.
-The drawback of a framework is that you are constrained to it, as you
-are constraint to use the routing algorithm provided by your telephone
-service. You also have to learn the framework interfaces, which in
-this analogy is the same as learning how to use a telephone.
-
-If you are interested in doing physics, a good HEP framework will save
-you much work. Next is a list of the more commonly used components of
-ROOT: Command Line Interpreter, Histograms and Fitting, Writing a
-Graphical User Interface, 2D Graphics, Input/Output , Collection
-Classes, Script Processor.
-
-There are also less commonly used components, as: 3D Graphics,
-Parallel Processing (PROOF), Run Time Type Identification (RTTI),
-Socket and Network Communication, Threads.
-
-#### Advantages of Frameworks
-
-The benefits of frameworks can be summarized as follows:
-
--   Less code to write - the programmer should be able to use and
-    reuse the majority of the existing code. Basic functionality, such
-    as fitting and histogramming are implemented and ready to use and
-    customize.
-
--   More reliable and robust code - the code inherited from a
-    framework has already been tested and integrated with the rest of
-    the framework.
-
--   More consistent and modular code - the code reuse provides
-    consistency and common capabilities between programs, no matter
-    who writes them. Frameworks make it easier to break programs into
-    smaller pieces.
-
--   More focus on areas of expertise - users can concentrate on their
-    particular problem domain. They do not have to be experts at
-    writing user interfaces, graphics, or networking to use the
-    frameworks that provide those services.
-
-### Why Object-Oriented?
-
-
-Object-Oriented Programming offers considerable benefits compared to
-Procedure-Oriented Programming:
-
--   Encapsulation enforces data abstraction and increases opportunity
-    for reuse.
-
--   Sub classing and inheritance make it possible to extend and modify
-    objects.
-
--   Class hierarchies and containment containment hierarchies provide
-    a flexible mechanism for modeling real-world objects and the
-    relationships among them.
-
--   Complexity is reduced because there is little growth of the global
-    state, the state is contained within each object, rather than
-    scattered through the program in the form of global variables.
-
--   Objects may come and go, but the basic structure of the program
-    remains relatively static, increases opportunity for reuse of
-    design.
-
-## Installing ROOT
-\index{install ROOT}
-
-To install ROOT you have the choice to
-download the binaries or the source. The source is quicker to transfer
-since it is only \~22 MB, but you will need to compile and link it. The
-binaries compiled with no debug information range from \~35 MB to \~45
-MB depending on the target platform.
-
-The installation and building of ROOT is described in Appendix A:
-Install and Build ROOT. You can download the binaries, or the source.
-The GNU g++ compiler on most UNIX platforms can compile ROOT.
-
-Before downloading a binary version make sure your machine contains the
-right run-time environment. In most cases it is not possible to run a
-version compiled with, e.g., gcc4.0 on a platform where only gcc 3.2 is
-installed. In such cases you'll have to install ROOT from source.
-
-ROOT is currently running on the following platforms: supported
-platforms
-
--   `GNU/Linux x86-32 (IA32) and x86-64 (AMD64)(GCC,Intel/icc,
-     Portland/PGCC,KAI/KCC)`
-
--   `Intel Itanium (IA64) GNU/Linux (GCC, Intel/ecc, SGI/CC) `
-
--   `FreeBSD and OpenBSD (GCC)`
-
--   `GNU/Hurd (GCC)`
-
--   `HP HP-UX 10.x (IA32) and 11 (IA64) (HP CC, aCC, GCC)`
-
--   `IBM AIX 4.1 (xlC compiler, GCC)`
-
--   `Sun Solaris for SPARC (SUN C++ compiler, GCC) `
-
--   `Sun Solaris for x86 (SUN C++ compiler, KAI/KCC)`
-
--   `Compaq Alpha (GCC, KAI/KCC, DEC/CXX)`
-
--   `SGI Irix 32 and 64 bits (GCC, KAI/KCC, SGI C++ compiler) `
-
--   `Windows >= 95 (Microsoft Visual C++ compiler, Cygwin/GCC) `
-
--   `MacOS X PPC, x86-32, x86-64 (GCC, Intel/ICC, IBM/xl)`
-
--   `PowerPC with GNU/Linux and GCC, Debian v2`
-
--   `PowerPC64 with GNU/Linux and GCC`
-
--   `ARM with GNU/Linux and GCC`
-
--   `LynxOS`
-
-## The Organization of the ROOT Framework
-
-
-Now after we know in abstract terms what the ROOT framework is, let us
-look at the physical directories and files that come with the ROOT
-installation. You may work on a platform where your system
-administrator has already installed ROOT. You will need to follow the
-specific development environment for your setup and you may not have
-write access to the directories. In any case, you will need an
-environment variable called `ROOTSYS`, which holds the path of the top
-ROOT directory.
-
-``` {.cpp}
-> echo $ROOTSYS
-/opt/root
-```
-
-In the `ROOTSYS` directory are examples, executables, tutorials,
-header tutorials files, and, if you opted to download it, the source
-is here. The directories of special interest to us are `bin`,
-`tutorials`, `lib`, `test`, and` include`. The next figure shows the
-contents of these directories.
-
-![ROOT framework directories](pictures/02000004.jpg)
-
-
-### \$ROOTSYS/bin
-
-
-The `bin` directory contains several executables.
-
-+---------------+------------------------------------------------------------+
-| `root`        | shows the ROOT splash screen and calls `root.exe`          |
-+---------------+------------------------------------------------------------+
-| `root.exe`    | the executable that `root` calls, if you use a debugger    |
-|               | such as `gdb`, you will need to run `root.exe` directly    |
-+---------------+------------------------------------------------------------+
-| `rootcling`   | is the utility ROOT uses to create a class dictionary for  |
-|               | Cling                                                       |
-+---------------+------------------------------------------------------------+
-| `rmkdepend`   | a modified version of `makedepend` that is used by the     |
-|               | ROOT build system                                          |
-+---------------+------------------------------------------------------------+
-| `root-config` | a script returning the needed compile flags and libraries  |
-|               | for projects that compile and link with ROOT               |
-+---------------+------------------------------------------------------------+
-| `proofd`      | a small daemon used to authenticate a user of ROOT         |
-|               | parallel processing capability (PROOF)                     |
-+---------------+------------------------------------------------------------+
-| `proofserv`   | the actual PROOF process, which is started by `proofd`     |
-|               | after a user, has successfully been authenticated          |
-+---------------+------------------------------------------------------------+
-| `rootd`       | is the daemon for remote ROOT file access (see the         |
-|               | **`TNetFile`**)                                            |
-+---------------+------------------------------------------------------------+
-
-### \$ROOTSYS/lib
-
-
-There are several ways to use ROOT, one way is to run the executable
-by typing `root` at the system prompt another way is to link with the
-ROOT libraries and make the ROOT classes available in your own program.
-
-Here is a short description of the most relevant libraries, the ones
-marked with a \* are only installed when the options specified them.
-
--   `libAsImage` is the image manipulation library
-
--   `libCling` is the C++ interpreter (Cling)
-
--   `libCore` is the Base classes
-
--   `libEG` is the abstract event generator interface classes
-
--   \*`libEGPythia` is the Pythia5 event generator interface
-
--   \*`libEGPythia6` is the Pythia6 event generator interface
-
--   `libFitPanel` contains the GUI used for fitting
-
--   `libGed` contains the GUI used for editing the properties of
-    histograms, graphs, etc.
-
--   `libGeom` is the geometry package (with builder and painter)
-
--   `libGpad` is the pad and canvas classes which depend on low level
-    graphics
-
--   `libGraf` is the 2D graphics primitives (can be used independent
-    of libGpad)
-
--   `libGraf3d` is the 3D graphics primitives
-
--   `libGui` is the GUI classes (depend on low level graphics)
-
--   `libGuiBld` is the GUI designer
-
--   `libGuiHtml` contains the embedded HTML browser
-
--   `libGX11` is the low level graphics interface to the X11 system
-
--   \*`libGX11TTF` is an add-on library to libGX11 providing TrueType
-    fonts
-
--   `libHbook` is for interface ROOT - HBOOK
-
--   `libHist` is the histogram classes (with accompanying painter
-    library)
-
--   `libHtml` is the HTML documentation generation system
-
--   `libMatrix` is the matrix and vector manipulation
-
--   `libMathCore` contains the core mathematics and physics vector
-    classes
-
--   `libMathMore` contains additional functions, interfacing the GSL
-    math library
-
--   `libMinuit` is the MINUIT fitter
-
--   `libNet` contains functionality related to network transfer
-
--   `libNew` is the special global new/delete, provides extra memory
-    checking and interface for shared memory (optional)
-
--   `libPhysics` contains the legacy physics classes (TLorentzVector,
-    etc.)
-
--   `libPostscript` is the PostScript interface
-
--   `libProof` is the parallel ROOT Facility classes
-
--   `libPython` provides the interface to Python
-
--   \*`libRFIO` is the interface to CERN RFIO remote I/O system.
-
--   \*`libRGL` is the interface to OpenGL.
-
--   `libReflex` is the runtime type database library used by Cling
-
--   `libRint` is the interactive interface to ROOT (provides command
-    prompt)
-
--   `libRIO` provides the functionality to write and read objects to
-    and from ROOT files
-
--   `libRooFit` is the RooFit fitting framework
-
--   `libRuby` is the interface to Ruby
-
--   `libSpectrum` provides functionality for spectral analysis
-
--   \*`libThread` is the interface to TThread classes
-
--   `libTMVA` contains the multivariate analysis toolkit
-
--   `libTree` is the TTree object container system
-
--   `libTreePlayer` is the TTree drawing classes
-
--   `libTreeViewer` is the graphical TTree query interface
-
-#### Library Dependencies
-
-![ROOT libraries dependencies](pictures/03000005.png)
-
-The libraries are designed and organized to minimize dependencies,
-such that you can load just enough code for the task at hand rather
-than having to load all libraries or one monolithic chunk. The core
-library (`libCore.so`) contains the essentials; it is a part of all
-ROOT applications. In the Figure 1-2 you see that libCore.so is made
-up of base classes, container classes, meta information classes,
-operating system specific classes, and the ZIP algorithm used for
-compression of the ROOT files.
-
-The Cling library (`libCling.so`) is also needed in all ROOT
-applications, and even by `libCore`. A
-program referencing only **`TObject`** only needs `libCore`;
-`libCling` will be opened automatically. To add the ability to read and write
-ROOT objects one also has to load `libRIO`. As one would expect, none of that
-depends on graphics or the GUI.
-
-Library dependencies have different consequences; depending on whether
-you try to build a binary, or you just try to access a class that is
-defined in a library.
-
-#### Linktime Library Dependencies
-
-When building your own executable you will have to link against the
-libraries that contain the classes you use. The ROOT reference guide
-states the library a class is reference guide defined in. Almost all
-relevant classes can be found in libraries returned by
-`root-config -glibs`; the graphics libraries are retuned by
-`root-config --libs`. These commands are commonly used in `Makefiles`.
-Using `root-config` instead of enumerating the libraries by hand
-allows you to link them in a platform independent way. Also, if ROOT
-library names change you will not need to change your Makefile.
-
-A batch program that does not have a graphic display, which creates,
-fills, and saves histograms and trees, only needs to link the core
-libraries (`libCore`, `libRIO`), `libHist` and `libTree`.
-If ROOT needs access to other libraries, it loads them dynamically.
-For example, if the **`TreeViewer`** is used, `libTreePlayer` and all
-libraries `libTreePlayer` depends on are loaded also. The dependent
-libraries are shown in the ROOT reference guide's library dependency
-graph. The difference between reference guide `libHist` and
-`libHistPainter` is that the former needs to be explicitly linked and
-the latter will be loaded automatically at runtime when ROOT needs it,
-by means of the Plugin Manager. plugin manager
-
-In the Figure 1-2, the libraries represented by green boxes outside of
-the core are loaded via the plugin manager plugin manager or
-equivalent techniques, while the white ones are not. Of course, if one
-wants to access a plugin library directly, it has to be explicitly
-linked. An example of a plugin library is `libMinuit`. To create and
-fill histograms you need to link `libHist.so`. If the code has a call
-to fit the histogram, the "fitter" will dynamically load libMinuit if
-it is not yet loaded.
-
-#### Plugins: Runtime Library Dependencies for Linking
-
-plugin manager The Plugin Manager **`TPluginManager`** allows
-postponing library dependencies to runtime: a plugin library will only
-be loaded when it is needed. Non-plugins will need to be linked, and
-are thus loaded at start-up. Plugins are defined by a base class (e.g.
-**`TFile`**) that will be implemented in a plugin, a tag used to
-identify the plugin (e.g. `^rfio:` as part of the protocol string),
-the plugin class of which an object will be created
-(e.g. **`TRFIOFile`**), the library to be loaded (in short
-`libRFIO.so` to RFIO), and the constructor to be called (e.g.
-"`TRFIOFile()`"). This can be specified in the `.rootrc` which already
-contains many plugin definitions, or by calls to
-`gROOT->GetPluginManager()->AddHandler()`.
-
-#### Library AutoLoading
-
-When using a class in Cling, e.g. in an interpreted source file, ROOT
-will automatically load the library that defines this class. On
-start-up, ROOT parses all files ending on `.rootmap` rootmap that are
-in one of the `$LD_LIBRARY_PATH` (or `$DYLD_LIBRARY_PATH` for `MacOS`,
-or `$PATH` for `Windows`). They contain class names and the library
-names that the class depends on. After reading them, ROOT knows which
-classes are available, and which libraries to load for them.
-
-When `TSystem::Load("ALib")` is called, ROOT uses this information to
-determine which libraries `libALib.so` depends on. It will load these
-libraries first. Otherwise, loading the requested library could cause
-a system (dynamic loader) error due to unresolved symbols.
-
-### \$ROOTSYS/tutorials
-
-
-tutorials The tutorials directory contains many example example
-scripts. They assume some basic knowledge of ROOT, and for the new
-user we recommend reading the chapters: "Histograms" and
-"Input/Output" before trying the examples. The more experienced user
-can jump to chapter "The Tutorials and Tests" to find more explicit
-and specific information about how to build and run the examples.
-
-The `$ROOTSYS/tutorials/` directory include the following
-sub-directories:
-
-`fft`: Fast Fourier Transform with the fftw package `fit`: Several
-examples illustrating minimization/fitting `foam`: Random generator in
-multidimensional space `geom`: Examples of use of the geometry package
-(**`TGeo`** classes) `gl`: Visualisation with OpenGL `graphics`: Basic
-graphics `graphs`: Use of **`TGraph`**, **`TGraphErrors`**, etc.
-`gui`: Scripts to create Graphical User Interface `hist`: Histogramming
-`image`: Image Processing `io`: Input/Output `math`: Maths and
-Statistics functions `matrix`: Matrices (**`TMatrix`**) examples
-`mlp`: Neural networks with **`TMultiLayerPerceptron`** `net`: Network
-classes (client/server examples) `physics`: LorentzVectors, phase
-space `pyroot`: Python tutorials `pythia`: Example with `pythia8`
-`quadp`: Quadratic Programming `smatrix`:
-Matrices with a templated package `spectrum`: Peak finder, background,
-deconvolutions `splot`: Example of the **`TSplot`** class
-(signal/background estimator) `sql`: Interfaces to SQL (mysql, oracle,
-etc) `thread`: Using Threads `tmva`: Examples of the MultiVariate
-Analysis classes `tree`: Creating Trees, Playing with Trees `unuran`:
-Interface with the unuram random generator library `xml`:
-Writing/Reading xml files
-
-You can execute the scripts in `$ROOTSYS/tutorials`
-(or sub-directories) by setting your current directory in the script
-directory or from any user directory with write access. Several
-tutorials create new files. If you have write access to the tutorials
-directory, the new files will be created in the tutorials directory,
-otherwise they will be created in the user directory.
-
-### \$ROOTSYS/test
-
-
-The test directory contains a set of examples example that represent
-all areas of the framework. When a new release is cut, the examples in
-this directory are compiled and run to test the new release's backward
-compatibility. The list of source files is described in chapter "The
-Tutorials and Tests".
-
-The `$ROOTSYS/test` directory is a gold mine of ROOT-wisdom nuggets,
-and we encourage you to explore and exploit it. We recommend the new
-users to read the chapter "Getting Started". The chapter "The
-Tutorials and Tests" has instructions on how to build all the programs
-and it goes over the examples `Event` and `stress`.
-
-### \$ROOTSYS/include
-
-
-The `include` directory contains all header files. It is especially
-important because the header files contain the class definitions.
-
-### \$ROOTSYS/\<library\>
-
-
-The directories we explored above are available when downloading the
-binaries. When downloading the source you also get a directory for
-each library with the corresponding header and source files, located
-in the `inc` and `src` subdirectories. To see what classes are in a
-library, you can check the `<library>/inc` directory for the list of
-class definitions. For example, the physics library `libPhysics.so`
-contains these class definitions:
-
-``` {.cpp}
-> ls -m $ROOTSYS/math/physics/inc/
-LinkDef.h, TFeldmanCousins.h, TGenPhaseSpace.h, TLorentzRotation.h,
-TLorentzVector.h, TQuaternion.h, TRobustEstimator.h, TRolke.h,
-TRotation.h, TVector2.h, TVector3.h
-```
-
-## How to Find More Information
-
-
-website The ROOT web site has up to date documentation. The ROOT
-source code automatically generates this documentation, so each class
-is explicitly documented on its own web page, which is always up to
-date with the latest official release of ROOT.
-
-The ROOT Reference Guide web pages can be found at class index
-reference guide <https://root.cern/doc/master/classes.html>. Each
-page contains a class description, and an explanation of each method.
-It shows the class inheritance tree and lets you jump to the parent
-class page by clicking on the class name. If you want more details,
-you can even see the source. There is a help page available in the
-little box on the upper right hand side of each class documentation
-page. You can see on the next page what a typical class documentation
-web page looks like. The ROOT web site also contains in addition to
-this Reference Guide, "How To's", a list of publications and example
-applications.
-
-### Class Reference Guide
-
-
-The top of any class reference page lets you jump to different parts
-of the documentation. The first line links to the class index and the
-index for the current module (a group of classes, often a library).
-The second line links to the ROOT homepage and the class overviews.
-The third line links the source information - a HTML version of the
-source and header file as well as the CVS (the source management
-system used for the ROOT development) information of the files. The
-last line links the different parts of the current pages.
-
-![](pictures/03000006.png)
-
-![Example of function documentation, with automatically generated LaTeX-like graphics](pictures/03000007.png)
-
-![Inheritance tree, showing what the current class derives from, and which classes inherit from it](pictures/03000008.png)
-
-![HTML version of the source file linking all types and most functions](pictures/03000009.png)
diff --git a/documentation/users-guide/LinearAlgebra.md b/documentation/users-guide/LinearAlgebra.md
deleted file mode 100644
index 7a9c4294e84e6..0000000000000
--- a/documentation/users-guide/LinearAlgebra.md
+++ /dev/null
@@ -1,1270 +0,0 @@
-# Linear Algebra in ROOT
-
-The linear algebra package is supposed to give a complete environment in
-ROOT to perform calculations like equation solving and eigenvalue
-decompositions. Most calculations are performed in double precision. For
-backward compatibility, some classes are also provided in single
-precision like **`TMatrixF`**, **`TMatrixFSym`** and **`TVectorF`**.
-Copy constructors exist to transform these into their double precision
-equivalent, thereby allowing easy access to decomposition and eigenvalue
-classes, only available in double precision.
-
-The choice was made not to provide the less frequently used complex
-matrix classes. If necessary, users can always reformulate the
-calculation in 2 parts, a real one and an imaginary part. Although, a
-linear equation involving complex numbers will take about a factor of 8
-more computations, the alternative of introducing a set of complex
-classes in this non-template library would create a major maintenance
-challenge.
-
-Another choice was to fill in both the upper-right corner and the
-bottom-left corner of a symmetric matrix. Although most algorithms use
-only the upper-right corner, implementation of the different matrix
-views was more straightforward this way. When stored only the
-upper-right part is written to file.
-
-For a detailed description of the interface, the user should look at the
-root reference guide at: <http://root.cern.ch/root/Reference.html>
-
-## Overview of Matrix Classes
-
-The figure below shows an overview of the classes available in the
-linear algebra library,` libMatrix.so`. At the center is the base class
-**`TMatrixDBase`** from which three different matrix classes,
-**`TMatrixD`**, **`TMatrixDSym`** and **`TMatrixDFSparse`** derive. The
-user can define customized matrix operations through the classes
-**`TElementActionD`** and **`TElementsPosActionD`**.
-
-![Overview of matrix classes](pictures/0300012D.png)
-
-Reference to different views of the matrix can be created through the
-classes on the right-hand side, see "Matrix Views". These references
-provide a natural connection to vectors.
-
-Matrix decompositions (used in equation solving and matrix inversion)
-are available through the classes on the left-hand side (see "Matrix
-Decompositions"). They inherit from the **`TDecompBase`** class. The
-Eigen Analysis is performed through the classes at the top, see "Matrix
-Eigen Analysis". In both cases, only some matrix types can be analyzed.
-For instance, **`TDecompChol`** will only accept symmetric matrices as
-defined **`TMatrixDSym`**. The assignment operator behaves somewhat
-different than of most other classes. The following lines will result in
-an error:
-
-``` {.cpp}
-   TMatrixD a(3,4);
-   TMatrixD b(5,6);
-   b = a;
-```
-
-It required to first resize matrix b to the shape of `a`.
-
-``` {.cpp}
-   TMatrixD a(3,4);
-   TMatrixD b(5,6);
-   b.ResizeTo(a);
-   b = a;
-```
-
-## Matrix Properties
-
-A matrix has five properties, which are all set in the constructor:
-
--   `precision` - float or double. In the first case you will use the
-    **`TMatrixF`** class family, in the latter case the **`TMatrixD`**
-    one;
-
--   `type` - general (**`TMatrixD`**), symmetric (**`TMatrixDSym`**) or
-    sparse (**`TMatrixDSparse`**);
-
--   `size` - number of rows and columns;
-
--   `index` - range start of row and column index. By default these
-    start at zero;
-
--   `sparse` `map` - this property is only relevant for a sparse matrix.
-    It indicates where elements are unequal zero.
-
-### Accessing Properties
-
-The following table shows the methods to access the information about
-the relevant matrix property:
-
-+-----------------------------+----------------------------------------------+
-| Method                      | Descriptions                                 |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetRowLwb` `()`      | row lower-bound index                        |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetRowUpb` `()`      | row upper-bound index                        |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetNrows` `()`       | number of rows                               |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetColLwb` `()`      | column lower-bound index                     |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetColUpb` `()`      | column upper-bound index                     |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetNcols` `()`       | number of columns                            |
-+-----------------------------+----------------------------------------------+
-| `Int_t GetNoElements` `()`  | number of elements, for a dense matrix this  |
-|                             | equals: `fNrows x fNcols`                    |
-+-----------------------------+----------------------------------------------+
-| `Double_t GetTol` `()`      | tolerance number which is used in            |
-|                             | decomposition operations                     |
-+-----------------------------+----------------------------------------------+
-| `Int_t *GetRowIndexArray`   | for sparse matrices, access to the row index |
-| `()`                        | of `fNrows+1` entries                        |
-+-----------------------------+----------------------------------------------+
-| `Int_t *GetColIndexArray`   | for sparse matrices, access to the column    |
-| `()`                        | index of `fNelems` entries                   |
-+-----------------------------+----------------------------------------------+
-
-The last two methods in this table are specific to the sparse matrix,
-which is implemented according to the Harwell-Boeing format. Here,
-besides the usual shape/size descriptors of the matrix like `fNrows`,
-`fRowLwb`, `fNcols` and `fColLwb`, we also store a row index,
-`fRowIndex` and column index, `fColIndex` for the elements unequal zero:
-
-+-----------------------------+----------------------------------------------+
-| `fRowIndex[0,..,fNrows]:`   | Stores for each row the index range of the   |
-|                             | elements in the data and column array        |
-+-----------------------------+----------------------------------------------+
-| `fColIndex[0,..,fNelems-1]: | Stores the column number for each data       |
-| `                           | element != 0.                                |
-+-----------------------------+----------------------------------------------+
-
-The code to print all matrix elements unequal zero would look like:
-
-``` {.cpp}
-   TMatrixDSparse a;
-   const Int_t *rIndex = a.GetRowIndexArray();
-   const Int_t *cIndex = a.GetColIndexArray();
-   const Double_t *pData = a.GetMatrixArray();
-   for (Int_t irow = 0; irow < a.getNrows(); irow++) {
-      const Int_t sIndex = rIndex[irow];
-      const Int_t eIndex = rIndex[irow+1];
-      for (Int_t index = sIndex; index < eIndex; index++) {
-         const Int_t icol = cIndex[index];
-         const Double_t data = pData[index];
-         printf("data(%d,%d) = %.4en",irow+a.GetfRowLwb(),
-         icol+a.GetColLwb(),data);
-      }
-   }
-```
-
-### Setting Properties
-
-The following table shows the methods to set some of the matrix
-properties. The resizing procedures will maintain the matrix elements
-that overlap with the old shape. The optional last argument `nr_zeros`
-is only relevant for sparse matrices. If supplied, it sets the number of
-non-zero elements. If it is smaller than the number overlapping with the
-old matrix, only the first (row-wise)` nr_zeros` are copied to the new
-matrix.
-
-+-----------------------------------------+----------------------------------+
-|               Method                    |            Descriptions          |
-+=========================================+==================================+
-| `SetTol` `(Double_t tol)`               | set the tolerance number         |
-+-----------------------------------------+----------------------------------+
-| `ResizeTo` `(Int_t nrows,Int_t ncols,`  | change matrix shape to `nrows` x |
-|                                         | `ncols`. Index will start at     |
-| `         Int_t nr_nonzeros=-1)`        | zero                             |
-+-----------------------------------------+----------------------------------+
-| `ResizeTo(Int_t row_lwb,Int_t row_upb,` | change matrix shape to           |
-|                                         |                                  |
-| `Int_t col_lwb,Int_t col_upb,`          | `row_lwb:row_upb` x              |
-|                                         | `col_lwb:col_upb`                |
-| `Int_t nr_nonzeros=-1)`                 |                                  |
-+-----------------------------------------+----------------------------------+
-| `SetRowIndexArray` `(Int_t *data)`      | for sparse matrices, set the row |
-|                                         | index. The array data should     |
-|                                         | contains at least` fNrows+1`     |
-|                                         | entries column lower-bound index |
-+-----------------------------------------+----------------------------------+
-| `SetColIndexArray` `(Int_t *data)`      | for sparse matrices, set the     |
-|                                         | column index. The array data     |
-|                                         | should contains at least         |
-|                                         | `fNelems` entries                |
-+-----------------------------------------+----------------------------------+
-| `SetSparseIndex` `(Int_t nelems new)`   | allocate memory for a sparse map |
-|                                         | of `nelems_new` elements and     |
-|                                         | copy (if exists) at most         |
-|                                         | `nelems_new` matrix elements     |
-|                                         | over to the new structure        |
-+-----------------------------------------+----------------------------------+
-| `SetSparseIndex`                        | copy the sparse map from matrix  |
-| `(const TMatrixDBase &a)`               | `a` Note that this can be a      |
-|                                         | dense matrix!                    |
-+-----------------------------------------+----------------------------------+
-| `SetSparseIndexAB`                      | set the sparse map to the same   |
-| `(const TMatrixDSparse &a,` `           | of the map of matrix `a` and `b` |
-| const TMatrixDSparse &b)`               |                                  |
-+-----------------------------------------+----------------------------------+
-
-The second half of the table is only relevant for sparse matrices. These
-methods define the sparse structure. It should be clear that a call to
-any of these methods has to be followed by a **`SetMatrixArray`** (...)
-which will supply the matrix data, see the next chapter "Creating and
-Filling a Matrix".
-
-## Creating and Filling a Matrix
-
-The matrix constructors are listed in the next table. In the simplest
-ones, only the number of rows and columns is given. In a slightly more
-elaborate version, one can define the row and column index range.
-Finally, one can also define the matrix data in the constructor. In
-Matrix Operators and Methods we will encounter more fancy constructors
-that will allow arithmetic operations.
-
-+--------------------------------------------------------------------------+
-| `TMatrixD(Int_t nrows,Int_t ncols)`                                      |
-|                                                                          |
-| `TMatrixD(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb)`      |
-|                                                                          |
-| `TMatrixD(Int_t nrows,Int_t ncols,const Double_t *data, Option_t option= |
-| "")`                                                                     |
-|                                                                          |
-| `TMatrixD(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,`      |
-|                                                                          |
-| `         const Double_t *data,Option_t *option="")`                     |
-+--------------------------------------------------------------------------+
-| `TMatrixDSym(Int_t nrows)`                                               |
-|                                                                          |
-| `TMatrixDSym(Int_t row_lwb,Int_t row_upb) `                              |
-|                                                                          |
-| `TMatrixDSym(Int_t nrows,const Double_t *data,Option_t *option="")`      |
-|                                                                          |
-| `TMatrixDSym(Int_t row_lwb,Int_t row_upb,const Double_t *data, Option_t  |
-| *opt="")            `                                                    |
-+--------------------------------------------------------------------------+
-| `TMatrixDSparse(Int_t nrows,Int_t ncols)`                                |
-|                                                                          |
-| `TMatrixDSparse(Int_t row_lwb,Int_t row_upb,Int_t col_lwb, Int_t col_upb |
-| )`                                                                       |
-|                                                                          |
-| `TMatrixDSparse(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb, |
-| `                                                                        |
-|                                                                          |
-| `               Int_t nr_nonzeros,Int_t *row,Int_t *col,Double_t *data)` |
-+--------------------------------------------------------------------------+
-
-If only the matrix shape is defined in the constructor, matrix data has
-to be supplied and possibly the sparse structure. In "Setting
-Properties" was discussed how to set the sparse structure.
-
-Several methods exist to fill a matrix with data:
-
-`SetMatrixArray(const Double_t*data,Option_t*option="")`, copies the
-array data. If option`="F"`, the array fills the matrix column-wise else
-row-wise. This option is only implemented for **`TMatrixD`** and
-**`TMatrixDSym`**. It is expected that the array data contains at least
-`fNelems` entries.
-
-`SetMatrixArray(Int_t nr,Int_t *irow,Int_t *icol,Double_t *data)`, is
-only available for sparse matrices. The three arrays should each contain
-`nr` entries with row index, column index and data entry. Only the
-entries with non-zero data value are inserted!
-
-`operator() `or `operator[]`, these operators provide the easiest way to
-fill a matrix but are in particular for a sparse matrix expensive. If no
-entry for slot (`i,j`) is found in the sparse index table it will be
-entered, which involves some memory management! Therefore, before
-invoking this method in a loop it is wise to set the index table first
-through a call to the `SetSparseIndex` method.
-
-`SetSub(Int_t row_lwb,Int_t col_lwb,const TMatrixDBase &source)`, the
-matrix to be inserted at position `(row_lwb,col_lwb)` can be both, dense
-or sparse.
-
-`Use(...)` allows inserting another matrix or data array without
-actually copying the data. Next table shows the different flavors for
-the different matrix types.
-
-+--------------------------------------------------------------------------+
-| `Use(TMatrixD &a)`                                                       |
-|                                                                          |
-| `Use(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,Double_t *d |
-| ata)`                                                                    |
-|                                                                          |
-| `Use(Int_t nrows,Int_t ncols,Double_t *data)`                            |
-+--------------------------------------------------------------------------+
-| `Use(TMatrixDSym &a)`                                                    |
-|                                                                          |
-| `Use(Int_t nrows,Double_t *data)`                                        |
-|                                                                          |
-| `Use(Int_t row_lwb,Int_t row_upb,Double_t *data)`                        |
-+--------------------------------------------------------------------------+
-| `Use(TMatrixDSparse &a)`                                                 |
-|                                                                          |
-| `Use(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,Int_t nr_no |
-| nzeros,`                                                                 |
-|                                                                          |
-| `    Int_t *pRowIndex,Int_t *pColIndex,Double_t *pData)`                 |
-|                                                                          |
-| `Use(Int_t nrows,Int_t ncols,Int_t nr_nonzeros,Int_t *pRowIndex,`        |
-|                                                                          |
-| `    Int_t *pColIndex,Double_t *pData)`                                  |
-+--------------------------------------------------------------------------+
-
-Below follow a few examples of creating and filling a matrix. First we
-create a Hilbert matrix by copying an array.
-
-``` {.cpp}
-   TMatrixD h(5,5);
-   TArrayD data(25);
-   for (Int_t = 0; i < 25; i++) {
-      const Int_t ir = i/5;
-      const Int_t ic = i%5;
-      data[i] = 1./(ir+ic);
-   }
-   h.SetMatrixArray(data.GetArray());
-```
-
-We also could assign the data array to the matrix without actually
-copying it.
-
-``` {.cpp}
-   TMatrixD h; h.Use(5,5,data.GetArray());
-   h.Invert();
-```
-
-The array `data` now contains the inverted matrix. Finally, create a
-unit matrix in sparse format.
-
-``` {.cpp}
-   TMatrixDSparse unit1(5,5);
-   TArrayI row(5),col(5);
-   for (Int_t i = 0; i < 5; i++) row[i] = col[i] = i;
-   TArrayD data(5); data.Reset(1.);
-   unit1.SetMatrixArray(5,row.GetArray(),col.GetArray(),data.GetArray());
-
-   TMatrixDSparse unit2(5,5);
-   unit2.SetSparseIndex(5);
-   unit2.SetRowIndexArray(row.GetArray());
-   unit2.SetColIndexArray(col.GetArray());
-   unit2.SetMatrixArray(data.GetArray());
-```
-
-## Matrix Operators and Methods
-
-It is common to classify matrix/vector operations according to BLAS
-(Basic Linear Algebra Subroutines) levels, see following table:
-
-+-------------+---------------------+-----------------+---------------------------+
-| BLAS level  | operations          | example         | floating-point operations |
-+-------------+---------------------+-----------------+---------------------------+
-| 1           | vector-vector       | $x T y$         | $n$                       |
-+-------------+---------------------+-----------------+---------------------------+
-| 2           | matrix-vector       | $A x$           | $n2$                      |
-|             | matrix              |                 |                           |
-+-------------+---------------------+-----------------+---------------------------+
-| 3           | matrix-matrix       | $A B$           | $n3$                      |
-+-------------+---------------------+-----------------+---------------------------+
-
-Most level 1, 2 and 3 BLAS are implemented. However, we will present
-them not according to that classification scheme it is already boring
-enough.
-
-### Arithmetic Operations between Matrices
-
-+-------------------------+------------------------------------+--------------------+
-|        Description      |               Format               |       Comment      |
-+-------------------------+------------------------------------+--------------------+
-| `element`               | `C=A+B`                            |                    |
-|                         |                                    | `overwrites` $A$   |
-| `wise sum`              | `A+=B `                            |                    |
-|                         |                                    | $A = A+\alpha B$   |
-|                         | `Add` `(A,alpha,B) `               | `constructor`      |
-|                         |                                    |                    |
-|                         | `TMatrixD(A,TMatrixD::kPlus,B) `   |                    |
-+-------------------------+------------------------------------+--------------------+
-| `element wise`          | `C=A-B`                            | `overwrites` $A$   |
-| `subtraction`           | `A-=B `                            | `constructor`      |
-|                         |                                    |                    |
-|                         | `TMatrixD(A,TMatrixD::kMinus,B) `  |                    |
-+-------------------------+------------------------------------+--------------------+
-| `matrix multiplication` | `C=A*B`                            | `overwrites` $A$   |
-|                         |                                    |                    |
-|                         | `A*=B `                            |                    |
-|                         |                                    |                    |
-|                         | `C.Mult(A,B)`                      |                    |
-+-------------------------+------------------------------------+--------------------+
-|                         | `TMatrixD(A,TMatrixD::kMult,B)`    | `constructor of `  |
-|                         |                                    | $A.B$              |
-+-------------------------+------------------------------------+--------------------+
-|                         | `TMatrixD(A,`                      | `constructor of `  |
-|                         | `TMatrixD::kTransposeMult,B)`      | $A^{T}.B$          |
-+-------------------------+------------------------------------+--------------------+
-|                         | `TMatrixD(A,`                      | `constructor of `  |
-|                         | `TMatrixD::kMultTranspose,B)`      | $A.B^{T}$          |
-+-------------------------+------------------------------------+--------------------+
-| `element wise`          | `ElementMult(A,B) `                | `A(i,j)*= B(i,j)`  |
-| `multiplication`        |                                    |                    |
-|                         |                                    |                    |
-| `element wise division` | `ElementDiv(A,B)`                  | `A(i,j)/= B(i,j)`  |
-+-------------------------+------------------------------------+--------------------+
-
-### Arithmetic Operations between Matrices and Real Numbers
-
-+--------------------------+-------------------+----------------+
-| Description              | Format            | Comment        |
-+--------------------------+-------------------+----------------+
-| element wise sum         | `C=r+A`           | overwrites $A$ |
-|                          | `C=A+r`           |                |
-|                          | `A+=r`            |                |
-+--------------------------+-------------------+----------------+
-| element wise subtraction | `C=r-A`           | overwrites $A$ |
-|                          | `C=A-r`           |                |
-|                          | `A-=r`            |                |
-+--------------------------+-------------------+----------------+
-| matrix multiplication    | `C=r*A`           | overwrites $A$ |
-|                          | `C=A*r`           |                |
-|                          | `A*=r`            |                |
-+--------------------------+-------------------+----------------+
-
-### Comparisons and Boolean Operations
-
-The following table shows element wise comparisons between two matrices:
-
-+------------------------------------------+----------+-----------------------------+
-| Format                                   | Output   | Description                 |
-+------------------------------------------+----------+-----------------------------+
-| `A == B`                                 | `Bool_t` | equal to                    |
-+------------------------------------------+----------+-----------------------------+
-| `A != B `                                | matrix   | Not equal                   |
-|                                          |          |                             |
-| `A > B `                                 | matrix   | Greater than                |
-|                                          |          |                             |
-| `A >= B `                                | matrix   | Greater than or equal to    |
-|                                          |          |                             |
-| `A < B `                                 | matrix   | Smaller than                |
-|                                          |          |                             |
-| `A <= B`                                 | matrix   | Smaller than or equal to    |
-+------------------------------------------+----------+-----------------------------+
-| `AreCompatible(A,B) `                    | `Bool_t` | Compare matrix properties   |
-|                                          |          |                             |
-| `Compare(A,B) `                          |          | return summary of           |
-|                                          |          | comparison                  |
-| `VerifyMatrixIdentity(A,B,verb, maxDev)` | `Bool_t` |                             |
-|                                          |          | Check matrix identity       |
-|                                          |          | within `maxDev` tolerance   |
-+------------------------------------------+----------+-----------------------------+
-
-The following table shows element wise comparisons between matrix and real:
-
-+---------------------------------------+----------+-----------------------------+
-| Format                                | Output   | Description                 |
-+---------------------------------------+----------+-----------------------------+
-| `A == r`                              | `Bool_t` | equal to                    |
-|                                       |          |                             |
-| A != r                                | `Bool_t` | Not equal                   |
-|                                       |          |                             |
-| A \> r                                | `Bool_t` | Greater than                |
-|                                       | `Bool_t` |                             |
-| A \>= r                               |          | Greater than or equal to    |
-|                                       | `Bool_t` |                             |
-| A \< r                                | `Bool_t`  | Smaller than                |
-|                                       |          |                             |
-| A \<= r                               |          | Smaller than or equal to    |
-+---------------------------------------+----------+-----------------------------+
-| `VerifyMatrixValue(A,r,verb, maxDev)` | `Bool_t` | Compare matrix value with r |
-|                                       |          | within `maxDev` tolerance   |
-+---------------------------------------+----------+-----------------------------+
-
-### Matrix Norms
-
-+----------------------+--------------+----------------------------------------+
-| Format               | Output       | Description                            |
-+----------------------+--------------+----------------------------------------+
-| `A.RowNorm()`        | `Double_t`   | norm induced by the infinity vector    |
-|                      |              | norm, max*i*$\sum_{i}|A_{ij}|$         |
-| `A.NormInf()`        | `Double_t`   |                                        |
-|                      |              | max*i*$\sum_{i}|A_{ij}|$               |
-| `A.ColNorm()`        | `Double_t`   |                                        |
-|                      |              | norm induced by the 1 vector norm,     |
-| `A.Norm1()`          | `Double_t`   | max*j*$\sum_{i}|A_{ij}|$               |
-|                      |              |                                        |
-| `A.E2Norm()`         | `Double_t`   | max*j*$\sum_{i}|A_{ij}|$               |
-|                      |              |                                        |
-| `A.NonZeros()`       | `Int_t`      | Square of the Euclidean norm,          |
-|                      |              |                                        |
-| `A.Sum()`            | `Double_t`   | $\sum_{ji}(A_{ij}^{2})$                |
-|                      |              |                                        |
-| `A.Min()`            | `Double_t`   | number of elements unequal zero        |
-|                      |              |                                        |
-| `A.Max()`            | `Double_t`   | $\sum_{ji}(A_{ij})$                    |
-|                      |              |                                        |
-|                      |              | min*ij* $(A_{ij})$                     |
-|                      |              |                                        |
-|                      |              | max*ij* $(A_{ij})$                     |
-+----------------------+--------------+----------------------------------------+
-| `A.NormByColumn`     | `TMatrixD`   | $A_{ij}/= \nu_i$, divide               |
-| `(v,"D") `           |              | each matrix column by vector v. If the |
-|                      | `TMatrixD`   | second argument is "`M`", the column   |
-| `A.NormByRow`        |              | is multiplied.                         |
-| `(v,"D")`            |              |                                        |
-|                      |              | $A_{ij}/= \nu_j$, divide               |
-|                      |              | each matrix row by vector v. If the    |
-|                      |              | second argument is "`M`", the row is   |
-|                      |              | multiplied.                            |
-+----------------------+--------------+----------------------------------------+
-
-### Miscellaneous Operators
-
-+--------------------------+------------+---------------------------------------------+
-| Format                   | Output     | Description                                 |
-+--------------------------+------------+---------------------------------------------+
-| `A.Zero()`               | `TMatrixX` | $A_{ij} = 0$                                |
-+--------------------------+------------+---------------------------------------------+
-| `A.Abs()`                | `TMatrixX` | $A_{ij} = |A_{ij}|$                         |
-+--------------------------+------------+---------------------------------------------+
-| `A.Sqr()`                | `TMatrixX` | $A_{ij} = A_{ij}^2$                         |
-+--------------------------+------------+---------------------------------------------+
-| `A.Sqrt()`               | `TMatrixX` | $A_{ij} = \sqrt{(A_{ij})}$                  |
-+--------------------------+------------+---------------------------------------------+
-| `A.UnitMatrix()`         | `TMatrixX` | $A_{ij} = 1$ for *i ==j* else 0             |
-+--------------------------+------------+---------------------------------------------+
-| `A.Randomize`            | `TMatrixX` | $A_{ij} = (\beta-\alpha)\bigcup(0,1)+\alpha$|
-| `(alpha,beta,seed)`      |            | a random matrix is generated with           |
-|                          |            | elements uniformly distributed              |
-|                          |            | between $\alpha$ and $\beta$                |
-+--------------------------+------------+---------------------------------------------+
-| `A.T()`                  | `TMatrixX` | $A_{ij} = A_{ji}$                           |
-+--------------------------+------------+---------------------------------------------+
-| `A.Transpose(B)`         | `TMatrixX` | $A_{ij} = B_{ji}$                           |
-+--------------------------+------------+---------------------------------------------+
-| `A.Invert(&det)`         | `TMatrixX` | Invert matrix A. If the optional            |
-|                          |            | pointer to the `Double_t`                   |
-|                          |            | argument `det` is supplied, the             |
-|                          |            | matrix determinant is                       |
-|                          |            | calculated.                                 |
-+--------------------------+------------+---------------------------------------------+
-| `A.InvertFast(&det)     `| `TMatrixX` | like Invert but for matrices                |
-|                          |            | i =(6x6)a faster but less                   |
-|                          |            | accurate Cramer algorithm is                |
-|                          |            | used                                        |
-+--------------------------+------------+---------------------------------------------+
-| `A.Rank1Update(v,alpha)` | `TMatrixX` | Perform with vector v a rank 1              |
-|                          |            | operation on the matrix:                    |
-|                          |            | $A = A + \alpha.\nu.\nu^T$                  |
-+--------------------------+------------+---------------------------------------------+
-| `A.RandomizePD           | `TMatrixX` | $A_{ij} = (\beta-\alpha)\bigcup(0,1)+\alpha$|
-| `(alpha,beta,seed)`      |            | a random symmetric                          |
-|                          |            | positive-definite matrix is                 |
-|                          |            | generated with elements                     |
-|                          |            | uniformly distributed                       |
-|                          |            | between $\alpha$ and $\beta$                |
-+--------------------------+------------+---------------------------------------------+
-
-Output **`TMatrixX`** indicates that the returned matrix is of the same
-type as `A`, being **`TMatrixD`**, **`TMatrixDSym`** or
-**`TMatrixDSparse`**. Next table shows miscellaneous operations for
-**`TMatrixD`**.
-
-+--------------------------------+------------+---------------------------------+
-| Format                         | Output     | Description                     |
-+--------------------------------+------------+---------------------------------+
-| `A.Rank1Update(v1,v2,alpha)`   | `TMatrixD` | Perform with vector `v1` and    |
-|                                |            | `v2`, a rank 1 operation on the |
-|                                |            | matrix:                         |
-|                                |            | $A = A + \alpha.\nu.\nu2^T$     |
-+--------------------------------+------------+---------------------------------+
-
-## Matrix Views
-
-Another way to access matrix elements is through the matrix-view
-classes, **`TMatrixDRow`**, **`TMatrixDColumn`**, **`TMatrixDDiag`** and
-**`TMatrixDSub`** (each has also a const version which is obtained by
-simply appending const to the class name). These classes create a
-reference to the underlying matrix, so no memory management is involved.
-The next table shows how the classes access different parts of the
-matrix:
-
-+--------------------------------+-----------------------------------------+
-| class                          | view                                    |
-+--------------------------------+-----------------------------------------+
-|                                | $$ \left(\begin{array}{ccccc}           |
-|                                | x_{00} &     &        &     & x_{0n} \\ |
-|                                |        &     &        &     &        \\ |
-| `TMatrixDRow const(X,i)`       | x_{i0} & ... & x_{ij} & ... & x_{in} \\ |
-| `TMatrixDRow(X,i)`             |        &     &        &     &        \\ |
-|                                | x_{n0} &     &        &     & x_{nn}    |
-|                                | \end{array}\right)$$                    |
-+--------------------------------+-----------------------------------------+
-|                                | $$ \left(\begin{array}{ccccc}           |
-|                                | x_{00} &     & x_{0j} &     & x_{0n} \\ |
-|                                |        &     &  ...   &     &        \\ |
-| `TMatrixDColumn const(X,j)`    |        &     & x_{ij} &     &        \\ |
-| `TMatrixDColumn(X,j)`          |        &     &  ...   &     &        \\ |
-|                                | x_{n0} &     & x_{nj} &     & x_{nn}    |
-|                                | \end{array}\right)$$                    |
-+--------------------------------+-----------------------------------------+
-|                                | $$ \left(\begin{array}{ccccc}           |
-|                                | x_{00} &     &        &     & x_{0n} \\ |
-|                                |        & ... &        &     &        \\ |
-| `TMatrixDDiag const(X)`        |        &     &   ...  &     &        \\ |
-| `TMatrixDDiag(X)`              |        &     &        & ... &        \\ |
-|                                | x_{n0} &     &        &     & x_{nn}    |
-|                                | \end{array}\right)$$                    |
-+--------------------------------+-----------------------------------------+
-|                                | $$ \left(\begin{array}{ccccc}           |
-|                                | x_{00} &     &        &     & x_{0n} \\ |
-|                                |        &     &        &     &        \\ |
-| `TMatrixDSub const(X,i,l,j,k)` |        &     & x_{ij} & ... & x_{ik} \\ |
-| `TMatrixDSub(X,i,l,j,k)`       |        &     & x_{lj} & ... & x_{lk} \\ |
-|                                | x_{n0} &     &        &     & x_{nn}    |
-|                                | \end{array}\right)$$                    |
-+--------------------------------+-----------------------------------------+
-
-### View Operators
-
-For the matrix views **`TMatrixDRow`**, **`TMatrixDColumn`** and
-**`TMatrixDDiag`**, the necessary assignment operators are available to
-interact with the vector class **`TVectorD`**. The sub matrix view
-**`TMatrixDSub`** has links to the matrix classes **`TMatrixD`** and
-**`TMatrixDSym`**. The next table summarizes how the access individual
-matrix elements in the matrix views:
-
-+----------------------------------------+-----------------------------------+
-| Format                                 | Comment                           |
-+----------------------------------------+-----------------------------------+
-| `TMatrixDRow(A,i)(j)`                  | element $A_{ij}$                  |
-| `TMatrixDRow(A,i)[j]`                  |                                   |
-+----------------------------------------+-----------------------------------+
-| `TMatrixDColumn(A,j)(i)`               | element $A_{ij}$                  |
-| `TMatrixDColumn(A,j)[i]`               |                                   |
-+----------------------------------------+-----------------------------------+
-| `TMatrixDDiag(A(i)`                    | element $A_{ij}$                  |
-| `TMatrixDDiag(A[i]`                    |                                   |
-+----------------------------------------+-----------------------------------+
-| `TMatrixDSub(A(i)`                     | element $A_{ij}$                  |
-| `TMatrixDSub(A,rl,rh,cl,ch)(i,j)`      |                                   |
-|                                        | element $A_{rl+i,cl+j}$           |
-+----------------------------------------+-----------------------------------+
-
-The next two tables show the possible operations with real numbers, and
-the operations between the matrix views:
-
-+--------------------+-------------------------------+-----------------+
-|    Description     |      Format                   |    Comment      |
-+--------------------+-------------------------------+-----------------+
-| assign real        | `TMatrixDRow(A,i) = r`        | row $i$         |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDColumn(A,j) = r`     | column $j$      |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDDiag(A) = r`         | matrix diagonal |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDSub(A,i,l,j,k) = r`  | sub matrix      |
-+--------------------+-------------------------------+-----------------+
-
-+--------------------+-------------------------------+-----------------+
-| add real           | `TMatrixDRow(A,i) += r`       | row $i$         |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDColumn(A,j) += r`    | column $j$      |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDDiag(A) += r`        | matrix diagonal |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDSub(A,i,l,j,k) +=r`  | sub matrix      |
-+--------------------+-------------------------------+-----------------+
-
-+--------------------+-------------------------------+-----------------+
-| multiply with real | `TMatrixDRow(A,i) *= r`       | row $i$         |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDColumn(A,j) *= r`    | column $j$      |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDDiag(A) *= r`        | matrix diagonal |
-+--------------------+-------------------------------+-----------------+
-|                    | `TMatrixDSub(A,i,l,j,k) *= r` | sub matrix      |
-+--------------------+-------------------------------+-----------------+
-
-+-----------------------+---------------------------------+---------------------------------------+
-|       Description     |       Format                    |        Comment                        |
-+-----------------------+---------------------------------+---------------------------------------+
-|                       | `TMatrixDRow(A,i1) +=`          | add row $i2$ to row $i1$              |
-|                       | `TMatrixDRow const(B,i2)`       |                                       |
-+-----------------------+---------------------------------+---------------------------------------+
-| add matrix slice      | `TMatrixDColumn(A,j1) +=`       | add column $j2$ to column $j1$        |
-|                       | `TMatrixDColumn const(A,j2)`    |                                       |
-+-----------------------+---------------------------------+---------------------------------------+
-|                       | `TMatrixDDiag(A) +=`            | add $B$ diagonal to $A$ diagonal      |
-|                       | `TMatrixDDiag const(B)`         |                                       |
-+-----------------------+---------------------------------+---------------------------------------+
-
-+-----------------------+---------------------------------+---------------------------------------+
-|                       | `TMatrixDRow(A,i1) *=`          | multiply row $i2$ with row $i1$       |
-|                       | `TMatrixDRow const(B,i2)`       | element wise                          |
-+-----------------------+---------------------------------+---------------------------------------+
-|                       | `TMatrixDColumn(A,j1) *=`       | multiply column $j2$ with column $j1$ |
-|                       | `TMatrixDColumn const(A,j2)`    | element wise                          |
-+-----------------------+---------------------------------+---------------------------------------+
-| multiply matrix slice | `TMatrixDDiag(A) *=`            | multiply $B$ diagonal with $A$        |
-|                       | `TMatrixDDiag const(B)`         | diagonal element wise                 |
-+-----------------------+---------------------------------+---------------------------------------+
-|                       | `TMatrixDSub(A,i1,l1,j1,k1) *=` | multiply sub matrix of $A$ with       |
-|                       | `TMatrixDSub(B,i2,l2,j2,k2)`    | sub matrix of $B$                     |
-+-----------------------+---------------------------------+---------------------------------------+
-|                       | `TMatrixDSub(A,i,l,j,k) *= B`   | multiply sub matrix of $A$ with       |
-|                       |                                 | matrix of $B$                         |
-+-----------------------+---------------------------------+---------------------------------------+
-
-In the current implementation of the matrix views, the user could
-perform operations on a symmetric matrix that violate the symmetry. No
-checking is done. For instance, the following code violates the
-symmetry.
-
-``` {.cpp}
-   TMatrixDSym A(5);
-   A.UnitMatrix();
-   TMatrixDRow(A,1)[0] = 1;
-   TMatrixDRow(A,1)[2] = 1;
-```
-
-### View Examples
-
-Inserting row `i1 `into row` i2` of matrix $A$
-can easily accomplished through:
-
-``` {.cpp}
-   TMatrixDRow(A,i1) = TMatrixDRow(A,i2)
-```
-
-Which more readable than:
-
-``` {.cpp}
-   const Int_t ncols = A.GetNcols();
-   Double_t *start = A.GetMatrixArray();
-   Double_t *rp1 = start+i*ncols;
-   const Double_t *rp2 = start+j*ncols;
-   while (rp1 < start+ncols) *rp1++ = *rp2++;
-```
-
-Check that the columns of a Haar -matrix of order `order` are indeed
-orthogonal:
-
-``` {.cpp}
-   const TMatrixD haar = THaarMatrixD(order);
-   TVectorD colj(1<<order);
-   TVectorD coll(1<<order);
-   for (Int_t j = haar.GetColLwb(); j <= haar.GetColUpb(); j++) {
-      colj = TMatrixDColumn_const(haar,j);
-      Assert(TMath::Abs(colj*colj-1.0) <= 1.0e-15);
-
-      for (Int_t l = j+1; l <= haar.GetColUpb(); l++) {
-         coll = TMatrixDColumn_const(haar,l);
-         Assert(TMath::Abs(colj*coll) <= 1.0e-15);
-      }
-   }
-```
-
-Multiplying part of a matrix with another part of that matrix (they can overlap)
-
-``` {.cpp}
-   TMatrixDSub(m,1,3,1,3) *= m.GetSub(5,7,5,7);
-```
-
-## Matrix Decompositions
-
-The linear algebra package offers several classes to assist in matrix
-decompositions. Each of the decomposition methods performs a set of
-matrix transformations to facilitate solving a system of linear
-equations, the formation of inverses as well as the estimation of
-determinants and condition numbers. More specifically the classes
-**`TDecompLU`**, **`TDecompBK`**, **`TDecompChol`**, **`TDecompQRH`** and
-**`TDecompSVD`** give a simple and consistent interface to the LU,
-Bunch-Kaufman, Cholesky, QR and SVD decompositions. All of these classes
-are derived from the base class **`TDecompBase`** of which the important
-methods are listed in next table:
-
-+-----------------------------------------------------+--------------------------------------+
-|                    Method                           |          Action                      |
-+-----------------------------------------------------+--------------------------------------+
-| `Bool_t Decompose()`                                | perform the matrix decomposition     |
-+-----------------------------------------------------+--------------------------------------+
-| `Double_t Condition()`                              | calculate ||*A*||1 ||*A*-1||1,       |
-|                                                     | see "Condition number"               |
-+-----------------------------------------------------+--------------------------------------+
-| `void Det(Double_t &d1,Double_t &d2)`               | the determinant is `d1` $2^{d_{2}}$. |
-|                                                     | Expressing the determinant this      |
-|                                                     | way makes under/over-flow very       |
-|                                                     | unlikely                             |
-+-----------------------------------------------------+--------------------------------------+
-| `Bool_t Solve(TVectorD &b)`                         | solve `Ax=b`; vector` b` is          |
-|                                                     | supplied through the argument and    |
-|                                                     | replaced with solution `x`           |
-+-----------------------------------------------------+--------------------------------------+
-| `TVectorD Solve(const TVectorD &b,Bool_t &ok)`      | solve `Ax=b; x` is returned          |
-+-----------------------------------------------------+--------------------------------------+
-| `Bool_t Solve(TMatrixDColumn &b)`                   | solve                                |
-|                                                     | `Ax=column(B,j)`;` column(B,j)`      |
-|                                                     | is supplied through the argument     |
-|                                                     | and replaced with solution `x`       |
-+-----------------------------------------------------+--------------------------------------+
-| `Bool_t TransSolve(TVectorD &b)`                    | solve $A^Tx=b;$ vector `b` is        |
-|                                                     | supplied through the argument and    |
-|                                                     | replaced with solution `x`           |
-+-----------------------------------------------------+--------------------------------------+
-| `TVectorD TransSolve(const TVectorD b, Bool_t &ok)` | solve $A^Tx=b;$ vector `x` is        |
-|                                                     | returned                             |
-+-----------------------------------------------------+--------------------------------------+
-| `Bool_t TransSolve(TMatrixDColumn &b)`              | solve                                |
-|                                                     | `ATx=column(B,j); column(B,j)` is    |
-|                                                     | supplied through the argument and    |
-|                                                     | replaced with solution `x`           |
-+-----------------------------------------------------+--------------------------------------+
-| `Bool_t MultiSolve(TMatrixD &B)`                    | solve $A^Tx=b;$. matrix `B` is       |
-|                                                     | supplied through the argument and    |
-|                                                     | replaced with solution `X`           |
-+-----------------------------------------------------+--------------------------------------+
-| `void Invert(TMatrixD &inv)`                        | call to `MultiSolve` with as         |
-|                                                     | input argument the unit matrix.      |
-|                                                     | Note that for a matrix (`m` x `n`)   |
-|                                                     | - $A$   with `m > n`, a              |
-|                                                     | pseudo-inverse is calculated         |
-+-----------------------------------------------------+--------------------------------------+
-| `TMatrixD Invert()`                                 | call to `MultiSolve` with as         |
-|                                                     | input argument the unit matrix.      |
-|                                                     | Note that for a matrix (`m` x `n`)   |
-|                                                     | - $A$   with `m > n`, a              |
-|                                                     | pseudo-inverse is calculated         |
-+-----------------------------------------------------+--------------------------------------+
-
-Through **`TDecompSVD`** and **`TDecompQRH`** one can solve systems for a (`m` x `n`)
- - $A$ with `m>n`. However, care has to be taken for
-methods where the input vector/matrix is replaced by the solution. For
-instance in the method **`Solve(b)`**, the input vector should have
-length m but only the first n entries of the output contain the
-solution. For the **`Invert(B)`** method, the input matrix B should have
-size (`m` x `n`) so that the returned (`m` x `n`) pseudo-inverse can fit
-in it.
-
-The classes store the state of the decomposition process of matrix $A$ in the
-user-definable part of **`TObject::fBits`**, see the next table. This guarantees the
-correct order of the operations:
-
-+---------------+-------------------------------------------------------------------------+
-| `kMatrixSet`  | $A$ `assigned`                                                          |
-|               |                                                                         |
-| `kDecomposed` | $A$ decomposed, bit `kMatrixSet` must have been set.                    |
-|               |                                                                         |
-| `kDetermined` | `det` $A$ calculated, bit `kDecomposed` must have been set.             |
-|               |                                                                         |
-| `kCondition`  | ||*A*||1 ||*A*-1||1 is calculated bit `kDecomposed` must have been set. |
-|               |                                                                         |
-| `kSingular`   | $A$ is singular                                                         |
-+---------------+-------------------------------------------------------------------------+
-
-
-The state is reset by assigning a new matrix through
-`SetMatrix(TMatrixD &A)` for **`TDecompBK`** and **`TDecompChol`**
-(actually `SetMatrix(`**`TMatrixDSym &A)`** and
-`SetMatrix(`**`TMatrixDSparse`** `&A)` for **`TMatrixDSparse`**).
-
-As the code example below shows, the user does not have to worry about
-the decomposition step before calling a solve method, because the
-decomposition class checks before invoking `Solve` that the matrix has
-been decomposed.
-
-``` {.cpp}
-   TVectorD b = ..;
-   TMatrixD a = ..;
-   .
-   TDecompLU lu(a);
-   Bool_t ok;
-   lu.Solve(b,ok);
-```
-
-In the next example, we show again the same decomposition but now
-performed in a loop and all necessary steps are manually invoked. This
-example also demonstrates another very important point concerning memory
-management! Note that the vector, matrix and decomposition class are
-constructed outside the loop since the dimensions of vector/matrix are
-constant. If we would have replaced `lu.SetMatrix(a)` by **`TDecompLU`**
-`lu(a)`, we would construct/deconstruct the array elements of `lu` on
-the stack*.*
-
-``` {.cpp}
-   TVectorD b(n);
-   TMatrixD a(n,n);
-   TDecompLU lu(n);
-   Bool_t ok;
-   for (....) {
-      b = ..;
-      a = ..;
-      lu.SetMatrix(a);
-      lu.Decompose();
-      lu.Solve(b,ok);
-   }
-```
-
-### Tolerances and Scaling
-
-The tolerance parameter `fTol` (a member of the base class
-**`TDecompBase`**) plays a crucial role in all operations of the
-decomposition classes. It gives the user a tool to monitor and steer the
-operations its default value is $\varepsilon$ where $1+\varepsilon=1$.
-
-If you do not want to be bothered by the following considerations, like
-in most other linear algebra packages, just set the tolerance with
-`SetTol` to an arbitrary small number. The tolerance number is used by
-each decomposition method to decide whether the matrix is near singular,
-except of course SVD that can handle singular matrices. This will be
-checked in a different way for any decomposition. For instance in LU, a
-matrix is considered singular in the solving stage when a diagonal
-element of the decomposed matrix is smaller than `fTol`. Here an
-important point is raised. The `Decompose()` method is successful as
-long no zero diagonal element is encountered. Therefore, the user could
-perform decomposition and only after this step worry about the tolerance
-number.
-
-If the matrix is flagged as being singular, operations with the
-decomposition will fail and will return matrices or vectors that are
-invalid. If one would like to monitor the tolerance parameter but not
-have the code stop in case of a number smaller than `fTol`, one could
-proceed as follows:
-
-``` {.cpp}
-   TVectorD b = ..;
-   TMatrixD a = ..;
-   .
-   TDecompLU lu(a);
-   Bool_t ok;
-   TVectorD x = lu.Solve(b,ok);
-   Int_t nr = 0;
-   while (!ok) {
-      lu.SetMatrix(a);
-      lu.SetTol(0.1*lu.GetTol());
-      if (nr++ > 10) break;
-      x = lu.Solve(b,ok);
-   }
-   if (x.IsValid())
-   cout << "solved with tol =" << lu.GetTol() << endl;
-   else
-   cout << "solving failed " << endl;
-```
-
-The observant reader will notice that by scaling the complete matrix by
-some small number the decomposition will detect a singular matrix. In
-this case, the user will have to reduce the tolerance number by this
-factor. (For CPU time saving we decided not to make this an automatic procedure).
-
-### Condition number
-
-The numerical accuracy of the solution `x` in `Ax = b` can be accurately
-estimated by calculating the condition number `k` of matrix $A$, which is defined as:
-
-$k = ||A||_{1}||A^{-1}||_{1}$ where $||A||_{1} = \underset{j}{max}(\sum_{i}|A_{ij}|)$
-
-A good rule of thumb is that if the matrix condition number is 10n,
-the accuracy in `x` is `15` - `n` digits for double precision.
-
-Hager devised an iterative method (W.W. Hager, Condition estimators,
-SIAM J. Sci. Stat. Comp., 5 (1984), pp. 311-316) to
-determine $||A^{-1}||_{1}$ without actually having to
-calculate $A^{-1}$. It is used when calling `Condition()`.
-
-A code example below shows the usage of the condition number. The matrix $A$
-is a (10x10) *Hilbert* matrix that is badly
-conditioned as its determinant shows. We construct a vector `b` by
-summing the matrix rows. Therefore, the components of the solution
-vector `x` should be exactly 1. Our rule of thumb to the 2.1012
-condition number predicts that the solution accuracy should be around
-
-`15 - 12 = 3`
-
-digits. Indeed, the largest deviation is 0.00055 in component 6.
-
-``` {.cpp}
-   TMatrixDSym H = THilbertMatrixDSym(10);
-   TVectorD rowsum(10);
-   for (Int_t irow = 0; irow < 10; irow++)
-   for (Int_t icol = 0; icol < 10; icol++)
-   rowsum(irow) += H(irow,icol);
-   TDecompLU lu(H);
-   Bool_t ok;
-   TVectorD x = lu.Solve(rowsum,ok);
-   Double_t d1,d2;
-   lu.Det(d1,d2);
-   cout << "cond:" << lu.Condition() << endl;
-   cout << "det :" << d1*TMath:Power(2.,d2) << endl;
-   cout << "tol :" << lu.GetTol() << endl;
-   x.Print();
-   cond:3.9569e+12
-   det :2.16439e-53
-   tol :2.22045e-16
-   Vector 10 is as follows
-     |          1   |
-   ------------------
-   0 |1
-   1 |1
-   2 |0.999997
-   3 |1.00003
-   4 |0.999878
-   5 |1.00033
-   6 |0.999452
-   7 |1.00053
-   8 |0.999723
-   9 |1.00006
-```
-
-### LU
-
-Decompose an `nxn` matrix $A$.
-
-``` {.cpp}
-   PA = LU
-```
-
-*P* permutation matrix stored in the index array `fIndex`: `j=fIndex[i]`
-indicates that row j and row` i `should be swapped. Sign of the
-permutation, $-1^n$, where `n` is the number of interchanges in the
-permutation, stored in `fSign`.
-
-*L* is lower triangular matrix, stored in the strict lower triangular
-part of `fLU.` The diagonal elements of *L* are unity and are not
-stored.
-
-*U* is upper triangular matrix, stored in the diagonal and upper
-triangular part of `fU`.
-
-The decomposition fails if a diagonal element of `fLU` equals 0.
-
-### Bunch-Kaufman
-
-Decompose a real symmetric matrix $A$
-
-``` {.cpp}
-   A = UDUT
-```
-
-*D* is a block diagonal matrix with 1-by-1 and 2-by-2 diagonal blocks
-*Dk*.
-
-*U* is product of permutation and unit upper triangular matrices:
-
-*U = Pn-1Un-1· · ·PkUk· · ·* where *k* decreases from *n* - 1 to 0 in
-steps of 1 or 2. Permutation matrix *Pk* is stored in `fIpiv`. *Uk* is a
-unit upper triangular matrix, such that if the diagonal block *Dk* is of
-order *s* (*s* = 1, 2), then
-
-$$ U_k = \underset{
-         \begin{array}{ccc}
-         k-s & s & n-k
-         \end{array}
-         }
-         {
-         \left(\begin{array}{ccc}
-         1 &  v  & 0 \\
-         0 &  1  & 0 \\
-         0 &  0  & 1
-         \end{array}\right)
-         }
-         \begin{array}{c}
-         k-s \\
-         s \\
-         n-k
-         \end{array}
-$$
-
-If *s* = 1, `Dk` overwrites $A$*(k, k)*, and v overwrites $A$*(0: k - 1, k)*.
-
-If *s* = 2, the upper triangle of `Dk` overwrites
-$A$*(k-1, k-1)*, $A$*(k-1,k)*, and $A$*(k, k)*, and v overwrites
-$A$*(0 : k - 2, k - 1 : k)*.
-
-### Cholesky
-
-Decompose a symmetric, positive definite matrix $A$
-
-``` {.cpp}
-   A = UTU
-```
-
-*U* is an upper triangular matrix. The decomposition fails if a diagonal
-element of `fU<=0`, the matrix is not positive negative.
-
-### QRH
-
-Decompose a (*m* x*n*) - matrix $A$ with *m >= n.*
-
-``` {.cpp}
-   A = QRH
-```
-
-*Q* orthogonal (*m* x *n*) - matrix, stored in `fQ`;
-
-*R* upper triangular (*n* x *n*) - matrix, stored in `fR`;
-
-*H* (*n* x *n*) - Householder matrix, stored through;
-
-`fUp` n - vector with Householder up's;
-
-`fW` n - vector with Householder beta's.
-
-The decomposition fails if in the formation of reflectors a zero
-appears, i.e. singularity.
-
-### SVD
-
-Decompose a (*m* x *n*) - matrix $A$ with *m >= n*.
-
-``` {.cpp}
-   A = USVT
-```
-
-*U* (*m* x *m*) orthogonal matrix, stored in `fU`;
-
-*S* is diagonal matrix containing the singular values. Diagonal stored
-in vector `fSig` which is ordered so that
-`fSig[0] >= fSig[1] >= ... >= fSig[n-1]`;
-
-*V* (*n* x *n*) orthogonal matrix, stored in `fV`.
-
-The singular value decomposition always exists, so the decomposition
-will (as long as m >= n) never fail. If *m* \< *n*, the user should add
-sufficient zero rows to $A$, so that *m* == *n*.
-In the `SVD`, `fTol` is used to set the threshold on the minimum allowed
-value of the singular values: `min singular = fTol maxi(Sii)`.
-
-## Matrix Eigen Analysis
-
-Classes **`TMatrixDEigen`** and **`TMatrixDSymEigen`** compute
-eigenvalues and eigenvectors for general dense and symmetric real
-matrices, respectively. If matrix $A$ is symmetric, then
-$A = V.D.V^{T}$, where the eigenvalue matrix $D$ is diagonal and the eigenvector matrix
-$V$ is orthogonal. That is, the diagonal values of $D$ are the eigenvalues,
-and $V.V^{T} = I$, where $I$ - is the identity matrix.
-The columns of $V$ represent the
-eigenvectors in the sense that $A.V = V.D$. If $A$ is not
-symmetric, the eigenvalue matrix $D$ is block
-diagonal with the real eigenvalues in 1-by-1 blocks and any complex
-eigenvalues, `a+i*b`, in 2-by-2 blocks, `[a,b;-b,a]`. That is, if the
-complex eigenvalues look like:
-
-$$
-   \left(\begin{array}{cccccc}
-   u+iv &   .  &   .  &   .  &   .  &   .  \\
-     .  & u-iv &   .  &   .  &   .  &   .  \\
-     .  &   .  & a+ib &   .  &   .  &   .  \\
-     .  &   .  &   .  & a-ib &   .  &   .  \\
-     .  &   .  &   .  &   .  &   x  &   .  \\
-     .  &   .  &   .  &   .  &   .  &   y
-   \end{array}\right)
-$$
-then $D$ looks like:
-$$
-   \left(\begin{array}{cccccc}
-     u  &   v  &   .  &   .  &   .  &   .  \\
-    -v  &   u  &   .  &   .  &   .  &   .  \\
-     .  &   .  &   a  &   b  &   .  &   .  \\
-     .  &   .  &   .  &  -b  &   a  &   .  \\
-     .  &   .  &   .  &   .  &   x  &   .  \\
-     .  &   .  &   .  &   .  &   .  &   y
-   \end{array}\right)
-$$
-
-This keeps $V$ a real matrix in both symmetric
-and non-symmetric cases, and $A.V = V.D$. The matrix $V$ may be badly conditioned,
-or even singular, so the validity of the equation $A = V.D.V^{-1}$ depends upon the
-condition number of $V$. Next table shows the
-methods of the classes **`TMatrixDEigen`** and **`TMatrixDSymEigen`** to
-obtain the eigenvalues and eigenvectors. Obviously,
-**`MatrixDSymEigen`** constructors can only be called with
-**`TMatrixDSym`**:
-
-+------------------------------+-----------+------------------------------------+
-| Format                       | Output    | Description                        |
-+------------------------------+-----------+------------------------------------+
-| `eig.GetEigenVectors` `()`   | `TMatrixD | eigenvectors for both              |
-|                              | `         | `TMatrixDEigen` and                |
-|                              |           | `TMatrixDSymEigen`                 |
-+------------------------------+-----------+------------------------------------+
-| `eig.GetEigenValues` `()`    | `TVectorD | eigenvalues vector for             |
-|                              | `         | `TMatrixDSymEigen`                 |
-+------------------------------+-----------+------------------------------------+
-| `eig.GetEigenValues()`       | `TMatrixD | eigenvalues matrix for             |
-|                              | `         | `TMatrixDEigen`                    |
-+------------------------------+-----------+------------------------------------+
-| `eig.GetEigenValuesRe` `()`  | `TVectorD | real part of eigenvalues for       |
-|                              | `         | `TMatrixDEigen`                    |
-+------------------------------+-----------+------------------------------------+
-| `eig.GetEigenValuesIm` `()`  | `TVectorD | imaginary part of eigenvalues for  |
-|                              | `         |                                    |
-|                              |           | `TMatrixDEigen`                    |
-+------------------------------+-----------+------------------------------------+
-
-Below, usage of the eigenvalue class is shown in an example where it is
-checked that the square of the singular values of a matrix
-$c$ are identical to the eigenvalues
-of $c^{T}$. $c$:
-
-``` {.cpp}
-   const TMatrixD m = THilbertMatrixD(10,10);
-   TDecompSVD svd(m);
-   TVectorD sig = svd.GetSig(); sig.Sqr();
-   // Symmetric matrix EigenVector algorithm
-   TMatrixDSym mtm(TMatrixDBase::kAtA,m);
-   const TMatrixDSymEigen eigen(mtm);
-   const TVectorD eigenVal = eigen.GetEigenValues();
-   const Bool_t ok = VerifyVectorIdentity(sig,eigenVal,1,1.-e-14);
-```
-
-## Speed Comparisons
-
-Speed of four matrix operations have been compared between four matrix
-libraries, `GSL` `CLHEP`, `ROOT v3.10` and `ROOT v4.0`. Next figure
-shows the `CPU` time for these four operations as a function of the
-matrix size:
-
-1. `A*B` The execution time is measured for the sum of A \* Bsym,
-Bsym\* A and A \* B. Notice the matrix\_size3 dependence of execution
-time. `CLHEP` results are hampered by a poor implementation of symmetric
-matrix multiplications. For instance, for general matrices of size
-100x100, the time is 0.015 sec. while A \* Bsym takes 0.028 sec and
-Bsym\* A takes 0.059 sec.
-
-Both `GSL` and `ROOT v4.0` can be setup to use the hardware-optimized
-multiplication routines of the `BLAS` libraries. It was tested on a G4
-PowerPC. The improvement becomes clearly visible around sizes of (50x50)
-were the execution speed improvement of the Altivec processor becomes
-more significant than the overhead of filling its pipe.
-
-2. $A^{-1}$ Here, the time is measured for an in-place matrix inversion.
-
-Except for `ROOT v3.10`, the algorithms are all based on an
-`LU `factorization followed by forward/back-substitution. `ROOT v3.10`
-is using the slower Gaussian elimination method. The numerical accuracy
-of the `CLHEP` routine is poor:
-
-- up to 6x6 the numerical imprecise Cramer multiplication is hard-coded.
-For instance, calculating `U=H*H-1`, where `H` is a (5x5) Hilbert
-matrix, results in off-diagonal elements of $10^{-7}$ instead of the $10^{-13}$
-using an `LU `according to `Crout`.
-
-- scaling protection is non-existent and limits are hard-coded, as a
-consequence inversion of a Hilbert matrix for `sizes>(12x12)` fails. In
-order to gain speed the `CLHEP` algorithm stores its permutation info of
-the pivots points in a static array, making multi-threading not
-possible.
-
-`GSL` uses LU decomposition without the implicit scaling of `Crout`.
-Therefore, its accuracy is not as good. For instance a (10x10) Hilbert
-matrix has errors 10 times larger than the `LU Crout` result. In
-`ROOT v4.0`, the user can choose between the `Invert()` and
-`IvertFast()` routines, where the latter is using the Cramer algorithm
-for `sizes<7x7`. The speed graph shows the result for `InvertFast()`.
-
-3. `A*x=b` the execution time is measured for solving the linear
-equation `A*x=b`. The same factorizations are used as in the matrix
-inversion. However, only 1 forward/back-substitution has to be used
-instead of msize as in the inversion of (msize x msize) matrix. As a
-consequence the same differences are observed but less amplified. CLHEP
-shows the same numerical issues as in step the matrix inversion. Since
-ROOT3.10 has no dedicated equation solver, the solution is calculated
-through `x=A-1*b`. This will be slower and numerically not as stable.
-
-4. $(A^{T}*A)^{-1}*A^{T}$ timing results for calculation of the pseudo inverse
-of matrix a. The sequence of operations measures the impact of several
-calls to constructors and destructors in the `C++` packages versus a `C`
-library like `GSL`.
-
-![Speed comparison between the different matrix packages](pictures/030001A1.png)
diff --git a/documentation/users-guide/Makefile b/documentation/users-guide/Makefile
deleted file mode 100644
index 59c66efa8dd80..0000000000000
--- a/documentation/users-guide/Makefile
+++ /dev/null
@@ -1,98 +0,0 @@
-OUTDIR=output
-
-MDFILES1=Preface.md Introduction.md GettingStarted.md \
-	Histograms.md Graphs.md FittingHistograms.md ALittleC++.md Cling.md \
-	ObjectOwnership.md Graphics.md FoldersTasks.md InputOutput.md \
-	Trees.md MathLibraries.md LinearAlgebra.md AddingaClass.md \
-	CollectionClasses.md PhysicsVectors.md Geometry.md PythonRuby.md \
-	TutorialsandTests.md ExampleAnalysis.md Networking.md Threads.md \
-	PROOF.md WritingGUI.md SignalSlot.md HTMLDoc.md InstallandBuild.md
-
-MDFILES=ROOTUsersGuide.md $(MDFILES1)
-
-HTMLFILES=$(addprefix $(OUTDIR)/,$(MDFILES:.md=.html))
-PDFFILES=$(addprefix $(OUTDIR)/,$(MDFILES:.md=.pdf))
-
-LATEXA4PREFIX=ROOTUsersGuideA4
-LATEXLETTERPREFIX=ROOTUsersGuideLetter
-
-OPTIONS=-s -f markdown+smart --toc --toc-depth=2 --top-level-division=chapter --number-sections
-OPTIONS2=-s -f markdown+smart --toc --toc-depth=1 --top-level-division=chapter --number-sections
-
-OPTIONSHTML=-H css/github.css --mathjax
-OPTIONSEPUB=--mathml
-OPTIONSLATEXA4=--template=./template.tex --variable=geometry:a4paper -V geometry:margin=1.5cm
-OPTIONSLATEXLETTER=--template=./template.tex --variable=geometry:letterpaper -V geometry:margin=1.5cm
-OPTIONSPDF=--variable=geometry:a4paper -V geometry:margin=1.5cm
-
-.PHONY: pdfa4 pdfletter html epub pdf_chapters html_chapters
-
-all: pdfa4 pdfletter html epub pdf_chapters html_chapters
-
-$(LATEXA4PREFIX).tex: $(MDFILES)
-	pandoc $(OPTIONS) $(OPTIONSLATEXA4) -t latex ROOTUsersGuide.md warning.md $(MDFILES1) \
-	-o $(LATEXA4PREFIX).tex
-
-# on OSX pdflatex returns 1 even in case of success !?
-$(LATEXA4PREFIX).toc: $(LATEXA4PREFIX).tex
-	pdflatex -interaction=batchmode $(LATEXA4PREFIX).tex || true
-
-$(LATEXA4PREFIX).ind: $(LATEXA4PREFIX).toc ROOTUsersGuide.ist
-	makeindex -s ROOTUsersGuide.ist $(LATEXA4PREFIX).idx
-
-pdfa4: $(LATEXA4PREFIX).tex $(LATEXA4PREFIX).ind
-	@mkdir -p $(OUTDIR)
-	pdflatex -interaction=batchmode -output-directory=$(OUTDIR) $(LATEXA4PREFIX).tex || true
-
-$(LATEXLETTERPREFIX).tex: $(MDFILES)
-	pandoc $(OPTIONS) $(OPTIONSLATEXLETTER) -t latex ROOTUsersGuide.md warning.md $(MDFILES1) \
-	-o $(LATEXLETTERPREFIX).tex
-
-$(LATEXLETTERPREFIX).toc: $(LATEXLETTERPREFIX).tex
-	pdflatex -interaction=batchmode $(LATEXLETTERPREFIX).tex || true
-
-$(LATEXLETTERPREFIX).ind: $(LATEXLETTERPREFIX).toc ROOTUsersGuide.ist
-	makeindex -s ROOTUsersGuide.ist $(LATEXLETTERPREFIX).idx
-
-pdfletter: $(MDFILES) $(LATEXLETTERPREFIX).toc $(LATEXLETTERPREFIX).ind
-	@mkdir -p $(OUTDIR)
-	pdflatex -interaction=batchmode -output-directory=$(OUTDIR) $(LATEXLETTERPREFIX).tex || true
-
-html: $(MDFILES)
-	@mkdir -p $(OUTDIR)
-	@mkdir -p $(OUTDIR)/pictures
-	@cp -r pictures/* $(OUTDIR)/pictures
-	pandoc --quiet $(OPTIONS2) $(OPTIONSHTML) -t html ROOTUsersGuide.md warning.md $(MDFILES1) \
-	-o $(OUTDIR)/ROOTUsersGuide.html
-
-epub: $(MDFILES) metadata.xml title.txt
-	@mkdir -p $(OUTDIR)
-	pandoc $(OPTIONS) $(OPTIONSEPUB) --epub-metadata=metadata.xml \
-	title.txt ROOTUsersGuide.md warning.md $(MDFILES1) -o $(OUTDIR)/ROOTUsersGuide.epub
-
-# --number-offset unfortunately not supported in PDF output :(
-$(OUTDIR)/%.pdf: %.md
-	@mkdir -p $(OUTDIR)
-	@echo Generating PDF chapter: $@
-	@pandoc $(OPTIONS) $(OPTIONSPDF) warning.md $^ -o $@
-
-pdf_chapters: $(PDFFILES)
-
-$(OUTDIR)/%.html: %.md
-	@mkdir -p $(OUTDIR)
-	@echo Generating HTML chapter: $@
-	@echo % Chapter: $^ | sed -e "s/.md//" | sed -e "s/and/ and /" | sed -e "s/[A-Z]/ &/g" >> $@.txt
-	@cat warning.md >> $@.txt
-	@( OFFSET=$$( for F in $(MDFILES) ; do echo $$F ; done | \
-	   grep -n "^$^$$" | head -n1 | cut -d: -f1 ) && \
-	   OFFSET=`expr $$OFFSET - 1` && \
-	   pandoc $(OPTIONS) $(OPTIONSHTML) -t html $@.txt --number-offset $$OFFSET $^ -o $@ )
-
-html_chapters: $(HTMLFILES)
-
-clean:
-	rm -rf $(LATEXA4PREFIX).pdf $(LATEXLETTERPREFIX).pdf \
-	ROOTUsersGuide.html ROOTUsersGuide.epub \
-	$(LATEXA4PREFIX).{tex,dvi,ind,toc,out,log,idx,aux,ilg} \
-	$(LATEXLETTERPREFIX).{tex,dvi,ind,toc,out,log,idx,aux,ilg} \
-	$(PDFFILES) $(HTMLFILES) $(OUTDIR)
diff --git a/documentation/users-guide/MathLibraries.md b/documentation/users-guide/MathLibraries.md
deleted file mode 100644
index 77e61b871512c..0000000000000
--- a/documentation/users-guide/MathLibraries.md
+++ /dev/null
@@ -1,3181 +0,0 @@
-# Math Libraries in ROOT
-
-
-The aim of Math libraries in ROOT is to provide and to support a
-coherent set of mathematical and statistical functions. The latest
-developments have been concentrated in providing first versions of the
-`MathCore` and `MathMore` libraries, included in ROOT v5.08. Other
-recent developments include the new version of `MINUIT`, which has been
-re-designed and re-implemented in the C++ language. It is integrated in
-ROOT. In addition, an optimized package for describing small matrices
-and vector with fixed sizes and their operation has been developed
-(`SMatrix`). The structure is shown in the following picture.
-
-![Math libraries and packages](pictures/02000109.jpg)
-
-
-## MathCore Library
-
-`MathCore` provides a collection of functions and C++ classes for
-numerical computing. This library includes only the basic mathematical
-functions and algorithms and not all the functionality required by the
-physics community. A more advanced mathematical functionality is
-provided by the `MathMore` library. The current set of included classes,
-which are provided in the `ROOT::Math` namespace are:
-
-
--   Basic special functions like the gamma, beta and error function.
-
--   Mathematical functions used in statistics, such as the probability
-    density functions and the cumulative distributions functions (lower
-    and upper integral of the pdf's).
-
--   Generic function classes and interfaces
-   for evaluating one-dimensional  (`ROOT::Math::IBaseFunctiononeDim`) and  multi-dimensional functions
-    (`ROOT::Math::IBaseFunctionMultiDim`) and parametric function interfaces for evaluating functions with parameters in one
-    (`ROOT::Math::IParametricFunctionOneDim`) or multi dimensions (`ROOT::Math::IParametricFunctionMultiDim`).
-    A set of user convenient wrapper classes, such as `ROOT::Math::Functor` is provided for wrapping user-classes in the needed interface,
-    required to use the algorithms of the `ROOT` Mathematical libraries.
-
-- Numerical algorithms interfaces and in same cases default implementations for:
-    -  numerical integration;
-    -  numerical differentiation;
-    -  one dimensional root-finding;
-    -  one-dimensional minimization;
-    - multi-dimensional minimization (only the `ROOT::Math::Minimizer` interface)
-
-- Fitting classes: set of classes for fitting generic data sets. These classes are provided in the namespace `ROOT::Fit`.
-   They are describing separately in the Fitting chapter.
-
-The sets described above is independent of ROOT libraries and can be built as a set of standalone classes.
-In addition `MathCore` provides the following classes (depending on ROOT *libCore* library):
-
--  `TMath`: namespace with mathematical functions and basic function algorithms.
--  `TComplex`: class for complex numbers.
--   Random classes: the base class `TRandom` and the derived classes `TRandom1`, `TRandom2` and `TRandom3`, implementing the pseudo-random number generators.
-
-A detailed description for all `MathCore` classes is available in the Doxygen
-[online reference documentation](online reference documentation).
-
-## MathMore Library
-
-The `MathMore` library provides an advanced collection of functions and
-C++ classes for numerical computing. This is an extension of the
-functionality provided by the `MathCore` library.
-The `MathMore` library is implemented wrapping in C++ the GNU Scientific Library (GSL).
-The current set, provided in
-the `ROOT::Math` namespace
-include:
-
-- Special mathematical functions (like Bessel functions, Legendre polynomials, etc.. )
-
-- Additional mathematical functions used in statistics such as probability density
-functions, cumulative distributions functions and their inverse which are not in `MathCore` but present in
-the `GSL` library.
-
-- Numerical algorithms for one dimensional functions based on
-implementation of the GNU Scientific Library (GSL):
-
--   Numerical integration classes implementing the  interface **`ROOT::Math::Integrator`**
-    which is based on the Adaptive integration algorithms of QUADPACK
-
--   Numerical differentiation via **`ROOT::Math::GSLDerivator`**
-
--   Root finder implementing the  **`ROOT::Math::RootFinder`** interface, using different
-    solver algorithms from GSL
-
--   one-dimensional Minimization implementing the interface**`ROOT::Math::IMinimizer1D`**
-
--   Interpolation via **`ROOT::Math::Interpolation`**. All the GSL
-    interpolation types are supported
-
--   Function approximation based on Chebyshev polynomials via the class
-    **`ROOT::Math::Chebyshev`**
-
--   Random number generators and distributions based on GSL using the `ROOT::Math::Random<Engine_type>` class.
-
--   Polynomial evaluation and root solvers
-
-The mathematical functions are implemented as a set of free functions in
-the namespace **`ROOT::Math`**. The naming used for the special
-functions is the same proposed for the C++ standard (see C++ standard
-extension [proposal document](proposal document)).The `MathMore` library
-is implemented wrapping in C++ the GNU Scientific Library ( <GSL>).
-Building `MathMore` requires a version of GSL larger or equal 1.8. The
-source code of `MathMore` is distributed under the GNU General Public
-License.
-
-`MathMore` (and its ROOT Cling dictionary) can be built within ROOT
-whenever a GSL library is found in the system. The GSL library and
-header file location can be specified in the ROOT configure script, by
-doing:
-
-```
-./configure --with-gsl-incdir=... --with-gsl-libdir=...
-```
-
-`MathMore` can be built also a stand-alone library (without requiring
-ROOT) downloding the tar file from the Web at this link. In this case
-the library will not contain the dictionary information and therefore
-cannot be used interactively
-
-More information on the classes and functions present in `MathMore` is
-available in the
-[online reference documentation](online reference documentation).
-
-
-## TMath
-
-
-In the namespace, **`TMath`**, a collection of free functions is provided for the following functionality:
-
--   numerical constants (like `pi`, `e`, `h`, etc.);
-
--   trigonometric and elementary mathematical functions;
-
--   functions to work with arrays and collections (e.g. functions to find `min` and `max` of arrays);
-
--   statistic functions to work on array of data (e.g.  mean and `RMS` of arrays);
-
--   algorithms for binary search/hashing sorting;
-
--   special mathematical functions like `Bessel`, `Erf`, `Gamma`, etc.;
-
--   statistical functions, like common probability and cumulative
-(quantile) distributions
-
--   geometrical functions.
-
-For more details, see the reference documentation of **`TMath`** at
-[<http://root.cern.ch/root/htmldoc/TMath.html>](https://root.cern/doc/master/namespaceTMath.html).
-
-
-### Numerical Constants
-
-`TMath` offers a wide range of constants in the form of inline functions. Notice that they are not defined as C/C++ preprocessor macros. This set of functions includes one or more definitions for the following constants:
-
-* Pi.
-* Base of natural logarithm.
-* Velocity of light.
-* Gravitational constant (G).
-* Standard acceleration of gravity (g).
-* Standard acceleration of Gravity.
-* Plank's contant.
-* Boltzmann's and Steffan-Boltzmann's constants.
-* Avogadro's number.
-* Universal gas constant.
-* Molecular weight of dry air.
-* Dry air gas constant.
-* Euler-Mascheroni Constant.
-* Elementary charge.
-
-### Elementary Functions
-
-A set of miscellaneous elementary mathematical functions is provided along with a set of basic trigonometrical functions. Some of this functions refer to basic mathematical functions like the square root, the power to a number of the calculus of a logarithm, while others are used for number treatment, like rounding.
-
-Although there are some functions that are not in the standard C math library (like `Factorial`), most of the functionality offered here is just a wrapper of the first ones. Nevertheless, some of the them also offer some security checks or a better precision, like the trigonometrical functions `ASin(x)`, `ACos(x)` or `ATan(x)`.
-
-```{.cpp}
- // Generate a vector with 10 random numbers
- vector<double> v(10);
- std::generate(v.begin(), v.end(), rand);
-
- // Find the minimum value of the vector (iterator version)
- vector<double>::iterator it;
- it = TMath::LocMin(v.begin(), v.end());
- std::cout << *it << std::endl;
-
- // The same with the old-style version
- int i;
- i = TMath::LocMin(10, &v[0]);
- std::cout << v[i] << std::endl;
-```
-
-Another example of these functions can be found in $ROOTSYS/tutorials/permute.C.
-
-### Statistic Functions Operating on Arrays.
-
-This set of functions processes arrays to calculate:
-
-* Mean.
-* Median.
-* Geometrical mean.
-* Sample Standard Deviation (*RMS*).
-* The kth smallest element.
-
-These functions, as the array algorithms, have two different interfaces. An old-style one where the size of the array is passed as a first argument followed by a pointer to the array itself
-and a modern C++-like  interface that receives two iterators to it.
-
-```{.cpp}
- // Size of the array
- const int n = 100;
-
- // Vector v with random values
- vector<double> v(n);
- std::generate(v.begin(), v.end(), rand);
-
- // Weight vector w
- vector<double> w(n);
- std::fill(w.begin(), w.end, 1);
-
- double mean;
-
- // Calculate the mean of the vector
- // with iterators
- mean = TMath::Mean(v.begin(), v.end());
-
- // old-style
- mean = TMath::Mean(n, &v[0]);
-
- // Calculate the mean with a weight vector
- // with iterators
- mean = TMath::Mean(v.begin(), v.end(), w.begin());
-
- // old-style
- mean = TMath::Mean(n, &v[0], &w[0]);
-```
-
-### Special and Statistical Functions.
-
-`TMath` also provides special functions like Bessel, Error functions, Gamma or similar plus statistical mathematical functions, including probability density functions, cumulative distribution and their inverse.
-
-The majority of the special functions and the statistical distributions are provided also as free functions in the `ROOT::Math` namespace.
-See one of the next paragraph for the complete description of the functions provided in `ROOT::Math`.
-The user is encourage to use those versions of the algorithms rather than the ones in TMath.
-
-Functions not present in `ROOT::Math` and provided only by `TMath` are:
-
-* Special functions:
-  * DiLogarithm
-  * Struve
-
-* Statistical functions:
-   * KolmogorovProb
-   * Voigt function
-   * LaplaceDist
-   * Vavilov
-
-The example tutorial `GammaFun.C` and `mathBeta.C` in `$ROOTSYS/tutorials` shows an example of use of the `ROOT::Math` special functions
-
-
-
-## Random Numbers
-
-
-In ROOT pseudo-random numbers can be generated using the **`TRandom`**
-classes. 4 different types exist: **`TRandom`**, **`TRandom1`**,
-**`TRandom2`** and **`TRandom3`**. All they implement a different type
-of random generators. **`TRandom`** is the base class used by others. It
-implements methods for generating random numbers according to
-pre-defined distributions, such as Gaussian or Poisson.
-For random bit sequence generators, see **`ROOT::Math::LFSR`**.
-
-### TRandom
-
-
-Pseudo-random numbers are generated using a linear congruential random
-generator. The multipliers used are the same of the BSD `rand()` random
-generator. Its sequence is:
-
-$x_{n+1} = (ax_n + c) mod m$ with $a =1103515245$,
-$c = 12345$ and $m =2^{31}$.
-
-This type of generator uses a state of only a 32 bit integer and it has
-a very short period, 2^31^,about 10^9^, which can be exhausted in just
-few seconds. The quality of this generator is therefore BAD and it is
-strongly recommended to NOT use for any statistical study.
-
-### TRandom1
-
-
-This random number generator is based on the Ranlux engine, developed by
-M. Lüsher and implemented in Fortran by F. James. This engine has
-mathematically proven random proprieties and a long period of about
-10^171^. Various luxury levels are provided `(1,2,3,4)` and can be
-specified by the user in the constructor. Higher the level, better
-random properties are obtained at a price of longer CPU time for
-generating a random number. The level 3 is the default, where any
-theoretical possible correlation has very small chance of being
-detected. This generator uses a state of 24 32-bits words. Its main
-disadvantage is that is much slower than the others (see timing table).
-For more information on the generator see the following article:
-
--   F. James, "RANLUX: A Fortran implementation of the high quality
-    pseudo-random number generator of Lüscher", Computer Physics
-    Communication, 79 (1994) 111.
-
-### TRandom2
-
-
-This generator is based on the maximally equi-distributed combined
-Tausworthe generator by L'Ecuyer. It uses only 3 32-bits words for the
-state and it has a period of about 10^26^. It is fast and given its
-small states, it is recommended for applications, which require a very
-small random number size. For more information on the generator see the
-following article:
-
--   P. L'Ecuyer, "Maximally Equi-distributed Combined Tausworthe
-    Generators", Mathematics of Computation, 65, 213 (1996), 203-213.
-
-### TRandom3
-
-
-This is based on the Mersenne and Twister pseudo-random number
-generator, developed in 1997 by Makoto Matsumoto and Takuji Nishimura.
-The newer implementation is used, referred in the literature as MT19937.
-It is a very fast and very high quality generator with a very long
-period of 10^6000^. The disadvantage of this generator is that it uses a
-state of 624 words. For more information on the generator see the
-following article:
-
--   M. M. Matsumoto and T. Nishimura, "Mersenne twister: A
-    623-dimensionally equi-distributed uniform pseudorandom number
-    generator", ACM Trans. on Modeling and Computer Simulations, 8, 1,
-    (1998), 3-20.
-
-**`TRandom3`** is the recommended random number generator, and it is
-used by default in ROOT using the global ***`gRandom`*** object (see
-chapter gRandom).
-
-### Seeding the Generators
-
-
-The seeds for the generators can be set in the constructor or by using
-the `SetSeed` method. When no value is given the generator default seed
-is used, like 4357 for **`TRandom3`**. In this case identical sequence
-will be generated every time the application is run. When the 0 value is
-used as seed, then a unique seed is generated using a **`TUUID`**, for
-**`TRandom1`**, **`TRandom2`** and **`TRandom3`**. For **`TRandom`** the
-seed is generated using only the machine clock, which has a resolution
-of about 1 sec. Therefore identical sequences will be generated if the
-elapsed time is less than a second.
-
-### Examples of Using the Generators
-
-
-The method `Rndm()` is used for generating a pseudo-random number
-distributed between 0 and 1 as shown in the following example:
-
-``` {.cpp}
-   // use default seed
-   // (same random numbers will be generated each time)
-   TRandom3 r; // generate a number in interval ]0,1] (0 is excluded)
-   r.Rndm();
-   double x[100];
-   r.RndmArray(100,x); // generate an array of random numbers in ]0,1]
-   TRandom3 rdm(111);      // construct with a user-defined seed
-   // use 0: a unique seed will be automatically generated using TUUID
-   TRandom1 r1(0);
-   TRandom2 r2(0);
-   TRandom3 r3(0);
-   // seed generated using machine clock (different every second)
-   TRandom r0(0);
-```
-
-### Random Number Distributions
-
-
-The **`TRandom`** base class provides functions, which can be used by
-all the other derived classes for generating random variates according
-to predefined distributions. In the simplest cases, like in the case of
-the exponential distribution, the non-uniform random number is obtained
-by applying appropriate transformations. In the more complicated cases,
-random variates are obtained using acceptance-rejection methods, which
-require several random numbers.
-
-``` {.cpp}
-TRandom3 r;
-   // generate a gaussian distributed number with:
-   // mu=0, sigma=1 (default values)
-   double x1 = r.Gaus();
-   double x2 = r.Gaus(10,3);    // use mu = 10, sigma = 3;
-```
-
-The following table shows the various distributions that can be
-generated using methods of the **`TRandom`** classes. More information
-is available in the reference documentation for **`TRandom`**. In
-addition, random numbers distributed according to a user defined
-function, in a limited interval, or to a user defined histogram, can be
-generated in a very efficient way using **`TF1::`**GetRandom() or
-**`TH1::`**GetRandom().
-
-+-------------------------------------------+--------------------------------+
-| Distributions                             | Description                    |
-+-------------------------------------------+--------------------------------+
-| `Double_t Uniform(Double_t x1,Double_t x2 | Uniform random numbers between |
-| )`                                        | `x1,x2`                        |
-+-------------------------------------------+--------------------------------+
-| `Double_t Gaus(Double_t mu,Double_t sigma | Gaussian random numbers.       |
-| )`                                        |                                |
-|                                           | Default values: `mu=0`,        |
-|                                           | `sigma=1`                      |
-+-------------------------------------------+--------------------------------+
-| `Double_t Exp(Double_t tau)`              | Exponential random numbers     |
-|                                           | with mean tau.                 |
-+-------------------------------------------+--------------------------------+
-| `Double_t Landau(Double_t mean,Double_t s | Landau distributed random      |
-| igma)`                                    | numbers.                       |
-|                                           |                                |
-|                                           | Default values: `mean=0`,      |
-|                                           | `sigma=1`                      |
-+-------------------------------------------+--------------------------------+
-| `Double_t BreitWigner(Double_t mean,`     | Breit-Wigner distributed       |
-|                                           | random numbers.                |
-| `                     Double_t gamma)`    |                                |
-|                                           | Default values `mean=0`,       |
-|                                           | `gamma=1`                      |
-+-------------------------------------------+--------------------------------+
-| `Int_t Poisson(Double_t mean) `           | Poisson random numbers         |
-|                                           |                                |
-| `Double_t PoissonD(Double_t mean)`        |                                |
-+-------------------------------------------+--------------------------------+
-| `Int_t  Binomial(Int_t ntot,Double_t prob | Binomial Random numbers        |
-| )`                                        |                                |
-+-------------------------------------------+--------------------------------+
-| `Circle(Double_t &x,Double_t &y,Double_t  | Generate a random 2D point     |
-| r)`                                       | `(x,y)` in                     |
-|                                           |                                |
-|                                           | a circle of radius `r`         |
-+-------------------------------------------+--------------------------------+
-| `Sphere(Double_t &x,Double_t &y,`         | Generate a random 3D point     |
-|                                           | `(x,y,z)` in                   |
-| `       Double_t &z,Double_t r)`          |                                |
-|                                           | a sphere of radius `r`         |
-+-------------------------------------------+--------------------------------+
-| `Rannor(Double_t &a,Double_t &b)`         | Generate a pair of Gaussian    |
-|                                           | random                         |
-|                                           |                                |
-|                                           | numbers with `mu=0` and        |
-|                                           | `sigma=1`                      |
-+-------------------------------------------+--------------------------------+
-
-### UNURAN
-
-
-An interface to a new package, UNU.RAN, (Universal Non Uniform Random
-number generator for generating non-uniform pseudo-random numbers) was
-introduced in ROOT v5.16.
-
-UNU.RAN is an ANSI C library licensed under GPL. It contains universal
-(also called automatic or black-box) algorithms that can generate random
-numbers from large classes of continuous (in one or multi-dimensions),
-discrete distributions, empirical distributions (like histograms) and
-also from practically all standard distributions. An extensive online
-documentation is available at the UNU.RAN Web Site
-<http://statmath.wu-wien.ac.at/unuran/>
-
-The ROOT class **`TUnuran`** is used to interface the UNURAN package. It
-can be used as following:
-
--   With the UNU.RAN native, string API for pre-defined distributions
-    (see UNU.RAN documentation for the allowed string values at
-    <http://statistik.wu-wien.ac.at/unuran/doc/unuran.html> ):
-
-``` {.cpp}
-   TUnuran unr;
-   // initialize unuran to generate normal random numbers using
-   // a "arou" method
-   unr.Init("normal()","method=arou");
-   ...
-   // sample distributions N times (generate N random numbers)
-   for (int i = 0; i<N; ++i)
-      double x = unr.Sample();
-```
-
--   For continuous 1D distribution object via the class
-    **`TUnuranContDist`** that can be created for example from a
-    **`TF1`** function providing the pdf (probability density function)
-    . The user can optionally provide additional information via
-    `TUnuranContDist::SetDomain(min,max)` like the `domain()` for
-    generating numbers in a restricted region.
-
-``` {.cpp}
-   // 1D case: create a distribution from two TF1 object
-   // pointers pdfFunc
-   TUnuranContDist  dist( pdfFunc);
-   // initialize unuran passing the distribution and a string
-   // defining the method
-   unr.Init(dist, "method=hinv");
-   // sample distribution  N times (generate N random numbers)
-   for (int i = 0; i < N; ++i)
-      double x = unr.Sample();
-```
-
--   For multi-dimensional distribution via the class
-    **`TUnuranMultiContDist`**, which can be created from a the
-    multi-dimensional pdf.
-
-``` {.cpp}
-   // Multi- dimensional case from a TF1 (TF2 or TF3) objects
-   TUnuranMultiContDist  dist( pdfFuncMulti);
-   // the recommended method for multi-dimensional function is "hitro"
-   unr.Init(dist,"method=hitro");
-   // sample distribution  N times (generate N random numbers)
-   double x[NDIM];
-   for (int i = 0; i<N; ++i)
-      unr.SampleMulti(x);
-```
-
--   For discrete distribution via the class **`TUnuranDiscrDist`**,
-    which can be initialized from a **`TF1`** or from a vector of
-    probabilities.
-
-``` {.cpp}
-   // Create distribution from a vector of probabilities
-   double pv[NSize] = {0.1,0.2,...};
-   TUnuranDiscrDist dist(pv,pv+NSize);
-   // the recommended method for discrete distribution is
-   unr.Init(dist, "method=dgt");
-   // sample N times (generate N random numbers)
-   for (int i = 0; i < N; ++i)
-      int k = unr.SampleDiscr();
-```
-
--   For empirical distribution via the class **`TUnuranEmpDist`**. In
-    this case one can generate random numbers from a set of un-bin or
-    bin data. In the first case the parent distribution is estimated by
-    UNU.RAN using a gaussian kernel smoothing algorithm. The
-    **`TUnuranEmpDist`** distribution class can be created from a vector
-    of data or from **`TH1`** (using the bins or from its buffer for
-    un-binned data).
-
-``` {.cpp}
-   // Create distribution from a set of data
-   // vdata is an std::vector containing the data
-   TUnuranEmpDist  dist(vdata.begin(),vdata.end());
-   unr.Init(dist);
-   // sample N times (generate N random numbers)
-   for (int i = 0; i<N; ++i)
-      double x = unr.Sample();
-```
-
--   For some predefined distributions, like `Poisson` and `Binomial`,
-    one can use directly a function in the **`TUnuran`** class. This is
-    more convenient in passing distribution parameters than using
-    directly the string interface.
-
-``` {.cpp}
-   TUnuran unr;
-   // Initialize unuran to generate normal random numbers from the
-   // Poisson distribution with parameter mu
-   unr.InitPoisson(mu);
-   ...
-   // Sample distributions N times (generate N random numbers)
-   for (int i = 0; i<N; ++i)
-      int k = unr.SampleDiscr();
-```
-
-Functionality is also provided via the C++ classes for using a different
-random number generator by passing a TRandom pointer when constructing
-the **`TUnuran`** class (by default the ROOT ***`gRandom`*** is passed
-to UNURAN).
-
-### Performances of Random Numbers
-
-
-Here are the CPU times obtained using the four random classes on an
-`lxplus` machine with an Intel 64 bit architecture and compiled using gcc
-3.4:
-
-+--------------------+---------------+----------------+----------------+----------------+
-|                    | **`TRandom`** | **`TRandom1`** | **`TRandom2`** | **`TRandom3`** |
-|                    | (ns/call)     | (ns/call)      | (ns/call)      |  (ns/call)     |
-+--------------------+---------------+----------------+----------------+----------------+
-| `Rndm()`           | -             | -              | 6              |  9             |
-+--------------------+---------------+----------------+----------------+----------------+
-| `Gaus()`           | 31            | 161            | 35             |  42            |
-+--------------------+---------------+----------------+----------------+----------------+
-| `Rannor()`         | 116           | 216            | 126            |  130           |
-+--------------------+---------------+----------------+----------------+----------------+
-| `Poisson(m-10)`    | 147           | 1161           | 162            |  239           |
-+--------------------+---------------+----------------+----------------+----------------+
-| `Poisson(m=10)`    | 80            | 294            | 89             |  99            |
-| `UNURAN`           |               |                |                |                |
-+--------------------+---------------+----------------+----------------+----------------+
-
-### ROOT::Math::LFSR
-
-This namespace contains free functions to generate pseudo-random binary sequences,
-to match those often implemented in electronic chips, based on linear feedback shift
-registers (LFSR). A usage example can be found in $ROOTSYS/tutorials/math/PRBS.C.
-
-## Mathematical Functions
-
-
-The mathematical functions are present in both `MathCore` and `MathMore`
-libraries. All mathematical functions are implemented as free functions
-in the namespace **`ROOT::Math`**. The most used functions are in the
-`MathCore` library while the others are in the `MathMore` library. The
-functions in `MathMore` are all using the implementation of the GNU
-Scientific Library (GSL). The naming of the special functions is the
-same defined in the C++
-[Technical Report on Standard Library extensions](Technical Report on
-Standard Library extensions).
-The special functions are defined in the header file `Math/SpecFunc.h`.
-
-### Special Functions in MathCore
-
-
--   `ROOT::Math::beta(double x,double y) - `evaluates the beta function:
-    $$B(x,y) = \frac{\Gamma(x) \Gamma(y)}{\Gamma(x+y)}$$
-
--   `double ROOT::Math::erf(double x)` - evaluates the error function
-    encountered in integrating the normal
-    distribution:
-    $$erf(x) = \frac{2}{\sqrt{\pi}} \int_{0}^{x} e^{-t^2} dt$$
-
--   `double ROOT::Math::erfc(double x)` - evaluates the complementary
-    error function:
-    $$erfc(x) = 1 - erf(x) = \frac{2}{\sqrt{\pi}} \int_{x}^{\infty} e^{-t^2} dt$$
-
--   `double ROOT::Math::tgamma(double x)` - calculates the gamma
-    function:
-    $$\Gamma(x) = \int_{0}^{\infty} t^{x-1} e^{-t} dt$$
-
-### Special Functions in MathMore
-
-
--   `double ROOT::Math::assoc_legendre(unsigned l,unsigned m,double x) -`computes
-    the associated Legendre polynomials (with `m>=0`, `l>=m` and
-    `|x|<1)`:
-    $$P_{l}^{m}(x) = (1-x^2)^{m/2} \frac{d^m}{dx^m} P_{l}(x)$$
-
--   `double ROOT::Math::comp_ellint_1(double k)` - calculates the
-    complete elliptic integral of the first kind (with $0 \le k^2 \le 1$:
-    $$
-    K(k) = F(k, \pi / 2) = \int_{0}^{\pi /2} \frac{d \theta}{\sqrt{1 - k^2 \sin^2{\theta}}}
-    $$
-
--   `double ROOT::Math::comp_ellint_2(double k)` - calculates the
-    complete elliptic integral of the second kind (with $0 \le k^2 \le 1$):
-    $$
-    E(k) = E(k , \pi / 2) = \int_{0}^{\pi /2} \sqrt{1 - k^2 \sin^2{\theta}} d \theta
-    $$
-
--   `double ROOT::Math::comp_ellint_3(double n,double k)` - calculates
-    the complete elliptic integral of the third kind (with $0 \le k^2 \le 1$):
-    $$
-    \Pi (n, k, \pi / 2) = \int_{0}^{\pi /2} \frac{d \theta}{(1 - n \sin^2{\theta})\sqrt{1 - k^2 \sin^2{\theta}}}
-    $$
-
--   `double ROOT::Math::conf_hyperg(double a,double b,double z)` -
-    calculates the confluent hyper-geometric functions of the first
-    kind:
-    $$
-     _{1}F_{1}(a;b;z) = \frac{\Gamma(b)}{\Gamma(a)} \sum_{n=0}^{\infty} \frac{\Gamma(a+n)}{\Gamma(b+n)} \frac{z^n}{n!}
-    $$
-
--   `double ROOT::Math::conf_hypergU(double a,double b,double z)` -
-    calculates the confluent hyper-geometric
-    functions of the second kind, known also as Kummer function of the second type. It is
-    related to the confluent hyper-geometric function of the first kind:
-    $$
-    U(a,b,z) = \frac{ \pi}{ \sin{\pi b } } \left[ \frac{ _{1}F_{1}(a,b,z) } {\Gamma(a-b+1) } - \frac{ z^{1-b} { _{1}F_{1}}(a-b+1,2-b,z)}{\Gamma(a)} \right]
-    $$
-
--   `double ROOT::Math::cyl_bessel_i(double nu,double x)` - calculates
-    the modified Bessel function of the first kind, also called regular
-    modified (cylindrical) Bessel function:
-    $$
-    I_{\nu} (x) = i^{-\nu} J_{\nu}(ix) = \sum_{k=0}^{\infty} \frac{(\frac{1}{2}x)^{\nu + 2k}}{k! \Gamma(\nu + k + 1)}
-    $$
-
--   `double ROOT::Math::cyl_bessel_j(double nu,double x)` - calculates
-    the (cylindrical) Bessel function of the first kind, also called
-    regular (cylindrical) Bessel function:
-    $$
-    J_{\nu} (x) = \sum_{k=0}^{\infty} \frac{(-1)^k(\frac{1}{2}x)^{\nu + 2k}}{k! \Gamma(\nu + k + 1)}
-    $$
-
--   `double ROOT::Math::cyl_bessel_k(double nu,double x)` - calculates
-    the modified Bessel function of the second kind, also called
-    irregular modified (cylindrical) Bessel function for $x > 0$, $v > 0$:
-    $$
-    K_{\nu} (x) = \frac{\pi}{2} i^{\nu + 1} (J_{\nu} (ix) + iN(ix)) = \left\{ \begin{array}{cl} \frac{\pi}{2} \frac{I_{-\nu}(x) - I_{\nu}(x)}{\sin{\nu \pi}} & \mbox{for non-integral $\nu$} \\ \frac{\pi}{2} \lim{\mu \to \nu} \frac{I_{-\mu}(x) - I_{\mu}(x)}{\sin{\mu \pi}} & \mbox{for integral $\nu$} \end{array} \right.
-    $$
-
--   `double ROOT::Math::cyl_neumann(double nu,double x)` - calculates
-    the (cylindrical) Bessel function of the second kind, also called
-    irregular (cylindrical) Bessel function or (cylindrical) Neumann
-    function:
-    $$
-    N_{\nu} (x) = Y_{\nu} (x) = \left\{ \begin{array}{cl} \frac{J_{\nu} \cos{\nu \pi}-J_{-\nu}(x)}{\sin{\nu \pi}} & \mbox{for non-integral $\nu$} \\ \lim{\mu \to \nu} \frac{J_{\mu} \cos{\mu \pi}-J_{-\mu}(x)}{\sin{\mu \pi}} & \mbox{for integral $\nu$} \end{array} \right.
-    $$
-
--   `double ROOT::Math::ellint_1(double k,double phi)` - calculates
-    incomplete elliptic integral of the first kind (with $0 \le k^2 \le 1$):
-    $$
-    K(k) = F(k, \pi / 2) = \int_{0}^{\pi /2} \frac{d \theta}{\sqrt{1 - k^2 \sin^2{\theta}}}
-    $$
-
--   `double ROOT::Math::ellint_2(double k,double phi)` - calculates
-    the complete elliptic integral of the second kind (with $0 \le k^2 \le 1$):
-    $$
-    E(k) = E(k , \pi / 2) = \int_{0}^{\pi /2} \sqrt{1 - k^2 \sin^2{\theta}} d \theta
-    $$
-
--   `double ROOT::Math::ellint_3(double n,double k,double phi)` - calculates
-    the complete elliptic integral of the third kind (with $0 \le k^2 \le 1$):
-    $$
-    \Pi (n, k, \pi / 2) = \int_{0}^{\pi /2} \frac{d \theta}{(1 - n \sin^2{\theta})\sqrt{1 - k^2 \sin^2{\theta}}}
-    $$
-
--   `double ROOT::Math::expint(double x)` - calculates the exponential
-    integral:
-    $$
-    Ei(x) = - \int_{-x}^{\infty} \frac{e^{-t}}{t} dt
-    $$
-
--   `double ROOT::Math::hyperg(double a,double b,double c,double x)` -
-    calculates Gauss' hyper-geometric function:
-    $$
-    _{2}F_{1}(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a) \Gamma(b)} \sum_{n=0}^{\infty} \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)} \frac{x^n}{n!}
-    $$
-
--   `double ROOT::Math::legendre(unsigned l,double x)` - calculates
-    the Legendre polynomials for $l \ge 0$, $|x| \le 1$  in the Rodrigues
-    representation:
-    $$
-    P_{l}(x) = \frac{1}{2^l l!} \frac{d^l}{dx^l} (x^2 - 1)^l
-    $$
-
--   `double ROOT::Math::riemann_zeta(double x)` - calculates the
-    Riemann zeta function:
-    $$
-    \zeta (x) = \left\{ \begin{array}{cl} \sum_{k=1}^{\infty}k^{-x} & \mbox{for $x > 1$} \\ 2^x \pi^{x-1} \sin{(\frac{1}{2}\pi x)} \Gamma(1-x) \zeta (1-x) & \mbox{for $x < 1$} \end{array} \right.
-    $$
-
--   `double ROOT::Math::sph_bessel(unsigned n,double x)` - calculates
-    the spherical Bessel functions of the first kind (also called
-    regular spherical Bessel functions):
-    $$
-    j_{n}(x) = \sqrt{\frac{\pi}{2x}} J_{n+1/2}(x)
-    $$
-
--   `double ROOT::Math::sph_neumann(unsigned n,double x)` - calculates
-    the spherical Bessel functions of the second kind (also called
-    irregular spherical Bessel functions or spherical Neumann
-    functions):
-    $$
-    n_n(x) = y_n(x) = \sqrt{\frac{\pi}{2x}} N_{n+1/2}(x)
-    $$
-
-### Probability Density Functions (PDF)
-
-
-Probability density functions of various distributions. All the
-functions, apart from the discrete ones, have the extra location
-parameter `x0`, which by default is zero. For example, in the case of a
-gaussian `pdf`, `x0` is the `mean`, `mu`, of the distribution. All the
-probability density functions are defined in the header file
-`Math/DistFunc.h` and are part of the `MathCore` libraries. The
-definition of these functions is documented in the
-[reference doc for statistical functions](reference doc for statistical functions):
-
-``` {.cpp}
-double ROOT::Math::beta_pdf(double x,double a, double b);
-double ROOT::Math::binomial_pdf(unsigned int k,double p,unsigned int n);
-double ROOT::Math::breitwigner_pdf(double x,double gamma,double x0=0);
-double ROOT::Math::cauchy_pdf(double x,double b=1,double x0=0);
-double ROOT::Math::chisquared_pdf(double x,double r,double x0=0);
-double ROOT::Math::exponential_pdf(double x,double lambda,double x0=0);
-double ROOT::Math::fdistribution_pdf(double x,double n,double m,double x0=0);
-double ROOT::Math::gamma_pdf(double x,double alpha,double theta,double x0=0);
-double ROOT::Math::gaussian_pdf(double x,double sigma,double x0=0);
-double ROOT::Math::landau_pdf(double x,double s,double x0=0);
-double ROOT::Math::lognormal_pdf(double x,double m,double s,double x0=0);
-double ROOT::Math::normal_pdf(double x,double sigma,double x0=0);
-double ROOT::Math::poisson_pdf(unsigned int n,double mu);
-double ROOT::Math::tdistribution_pdf(double x,double r,double x0=0);
-double ROOT::Math::uniform_pdf(double x,double a,double b,double x0=0);
-```
-
-### Cumulative Distribution Functions (CDF)
-
-
-For all the probability density functions, we have the corresponding
-cumulative distribution functions and their complements. The functions
-with extension `_cdf` calculate the lower tail integral of the
-probability density function:
-
-$$
-D(x) = \int_{-\infty}^{x} p(x') dx'
-$$
-
-while those with the `cdf_c` extension calculate the upper tail of the
-probability density function, so-called in statistics the survival
-function. For example, the function:
-
-``` {.cpp}
-double ROOT::Math::gaussian_cdf(double x,double sigma,double x0=0);
-```
-evaluates the lower tail of the Gaussian distribution:
-$$
-D(x) = \int_{-\infty}^{x} {\frac{1}{\sqrt{2 \pi \sigma^2}}} e^{-(x'-x_0)^2 / 2\sigma^2} dx'
-$$
-
-while the function:
-
-``` {.cpp}
-double ROOT::Math::gaussian_cdf_c(double x, double sigma, double x0=0);
-```
-evaluates the upper tail of the Gaussian distribution:
-$$
-D(x) = \int_{x}^{+\infty} {\frac{1}{\sqrt{2 \pi \sigma^2}}} e^{-(x'-x_0)^2 / 2\sigma^2} dx'
-$$
-
-The cumulative distributions functions are defined in the header file
-`Math/ProbFunc.h`. The majority of the CDF's are present in the
-`MathCore`, apart from the `chisquared`, `fdistribution`, `gamma` and
-`tdistribution`, which are in the `MathMore` library.
-
-#### Inverse of the Cumulative Distribution Functions(Quantiles)
-
-For almost all the cumulative distribution functions (`_cdf`) and their
-complements (`_cdf_c`) present in the library, we provide the inverse
-functions. The inverse of the cumulative distribution function is called
-in statistics quantile function. The functions with the extension
-`_quantile` calculate the inverse of the cumulative distribution
-function (lower tail integral of the probability density function),
-while those with the *`quantile_c`* extension calculate the inverse of
-the complement of the cumulative distribution (upper tail integral). All
-the inverse distributions are in the MathMore library and are defined in
-the header file `Math/ProbFuncInv.h`.
-
-The following picture illustrates the available statistical functions
-(PDF, CDF and quantiles) in the case of the normal distribution.
-
-![PDF, CDF and quantiles in the case of the normal distribution](pictures/03000128.png)
-
-## Numerical Algorithms
-
-ROOT provides C++ classes implementing numerical algorithms to solve a wide set of problem, like:
-
-* Evaluation of function derivatives.
-* Evaluation of integrals.
-* Finding the roots of a function
-* Finding the minimum/maximum of a function
-
-In order to use these algorithm the user needs to provide a function.
-ROOT provides a common way of specifying them via some interfaces
-
-## ROOT::Math Function interfaces
-
-To get a consistency in the mathematical methods within ROOT, there exists a set of interfaces to define the basic behaviour of a mathematical function.
-In order to use the classes presented in this chapter, the mathematical functions defined by the user must inherit from any of the classes seen in the figure:
-
-
-![ROOT::Math Function interface structure](pictures/function-hierarchy.png)
-
-### One-dimensional Function Interfaces
-
-These interfaces are used for numerical algorithms operating only on  one-dimensional functions and cannot be applied to multi-dimensional functions.
-For this case the users needs to  define a function object which evaluates in one dimension, and the object  will have to derivate from the following:
-
-* `ROOT::Math::IBaseFunctionOneDim`: This class is the most basic function. Provides a method to evaluate the function given a value (simple double) by implementing
-`double operator() (const double )`. The user class defined only needs to reimplement the pure abstract method `double DoEval(double x)`,
-that will do the work of evaluating the function at point x.
-
-Example on how to create a class that represents a mathematical function. The user only has to override two methods from `IBaseFunctionOneDim`:
-
-```{.cpp}
-#include "Math/IFunction.h"
-
-class MyFunction: public ROOT::Math::IBaseFunctionOneDim
-{
-   double DoEval(double x) const
-   {
-      return x*x;
-   }
-
-   ROOT::Math::IBaseFunctionOneDim* Clone() const
-   {
-      return new MyFunction();
-   }
-};
-```
-
-
-* `ROOT::Math::IGradientFunctionOneDim`: Some of the numerical algorithm will need to calculate the derivatives of the function. In these cases, the user will have to provide the necessary code for
-  this to happen. The interface defined in `IGradientFunctionOneDim` introduced the method `double Derivative(double x)` that will return the derivative of the function at the point `x`. The class
-  inherit by the user will have to implement the abstract method `double DoDerivative(double x)`, leaving the rest of the class untouched.
-
-  Example for implementing a gradient one-dimensional function:
-
-```{.cpp}
-#include "Math/IFunction.h"
-
-class MyGradientFunction: public ROOT::Math::IGradientFunctionOneDim
-{
-public:
-   double DoEval(double x) const
-   {
-      return sin(x);
-   }
-
-   ROOT::Math::IBaseFunctionOneDim* Clone() const
-   {
-      return new MyGradientFunction();
-   }
-
-   double DoDerivative(double x) const
-   {
-      return -cos(x);
-   }
-
-};
-```
-
-### Multi-dimensional Function Interfaces
-
-
-The most generic case of a multidimensional function has similar approach. Some examples will be shown next. It is important to notice, that one dimensional functions can be also implemented through
-the interfaces that will be presented here. Nevertheless, the user needs to implement those following the indications of the previous chapter, for algorithm working exclusivly on one-dimensional
-functions. For algorithms working on both one-dimensional and multi-dimensional functions they should instead use this interface.
-
-* `ROOT::Math::IBaseFunctionMultiDim`: This interface provides the `double operator() (const double*)` that takes an array of doubles with all the values for the different dimensions. In this case,
-  the user has to provide the functionality for two different functions: `double DoEval(const double*)` and `unsigned int NDim()`. The first ones evaluates the function given the array that represents
-  the multiple variables. The second returns the number of dimensions of the function.
-
-   Example of implementing a  basic multi-dimensional function:
-
-```{.cpp}
-#include "Math/IFunction.h"
-
-class MyFunction: public ROOT::Math::IBaseFunctionMultiDim
-{
-public:
-   double DoEval(const double* x) const
-   {
-      return x[0] + sin(x[1]);
-   }
-
-   unsigned int NDim() const
-   {
-      return 2;
-   }
-
-   ROOT::Math::IBaseFunctionMultiDim* Clone() const
-   {
-      return new MyFunction();
-   }
-
-};
-```
-
-* `ROOT::Math::IGradientFunctionMultiDim`: This interface offers the same functionality as the base function plus the calculation of the derivative.
-It only adds the `double Derivative(double* x, uint ivar)` method for the user to implement. This method must implement the derivative of the function with respect to the variable indicated with the
-second parameter.
-
-Example of implementing a multi-dimensional gradient function
-
-```{.cpp}
-#include "Math/IFunction.h"
-
-class MyGradientFunction: public ROOT::Math::IGradientFunctionMultiDim
-{
-public:
-   double DoEval(const double* x) const
-   {
-      return x[0] + sin(x[1]);
-   }
-
-   unsigned int NDim() const
-   {
-      return 2;
-   }
-
-   ROOT::Math::IGradientFunctionMultiDim* Clone() const
-   {
-      return new MyGradientFunction();
-   }
-
-   double DoDerivative(const double* x, unsigned int ipar) const
-   {
-      if ( ipar == 0 )
-         return sin(x[1]);
-      else
-         return x[0] + x[1] * cos(x[1]);
-   }
-
-};
-```
-
-### Parametric Function Interfaces
-
-These interfaces, for evaluating multi-dimensional functions are used for fitting. These interfaces are defined in the header file
-`Math/IParamFunction.h`.
-See also the documentation of the `ROOT::Fit` classes in the Fitting chapter for more information.
-
-* **`ROOT::Math::IParametricFunctionMultiDim`**: Describes a multi dimensional parametric function. Similarly to the one dimensional version, the user needs to provide the
-method `void SetParameters(double* p)` as well as the getter methods `const double * Parameters()` and `uint NPar()`.
-Example of creating a parametric function:
-
-```{.cpp}
-#include "Math/IFunction.h"
-#include "Math/IParamFunction.h"
-
-class MyParametricFunction: public ROOT::Math::IParametricFunctionMultiDim
-{
-private:
-   const double* pars;
-
-public:
-   double DoEvalPar(const double* x, const double* p) const
-   {
-      return p[0] * x[0] + sin(x[1]) + p[1];
-   }
-
-   unsigned int NDim() const
-   {
-      return 2;
-   }
-
-   ROOT::Math::IParametricFunctionMultiDim* Clone() const
-   {
-      return new MyParametricFunction();
-   }
-
-   const double* Parameters() const
-   {
-      return pars;
-   }
-
-   void SetParameters(const double* p)
-   {
-      pars = p;
-   }
-
-   unsigned int NPar() const
-   {
-      return 2;
-   }
-};
-```
-
-* **`ROOT::Math::IParametricGradFunctionMultiDim`**:
-Provides an interface for parametric gradient multi-dimensional functions. In addition to function evaluation it provides the gradient with respect to the parameters,
-via the method `ParameterGradient()`. This interface is only used in case of some dedicated fitting algorithms, when is required or more efficient to provide derivatives with respect to the
-parameters. Here is an example:
-
-```{.cpp}
-#include "Math/IFunction.h"
-#include "Math/IParamFunction.h"
-
-class MyParametricGradFunction:
-          public ROOT::Math::IParametricGradFunctionMultiDim
-{
-private:
-   const double* pars;
-
-public:
-   double DoEvalPar(const double* x, const double* p) const
-   {
-      return p[0] * x[0] + sin(x[1]) + p[1];
-   }
-
-   unsigned int NDim() const
-   {
-      return 2;
-   }
-
-   ROOT::Math::IParametricGradFunctionMultiDim* Clone() const
-   {
-      return new MyParametricGradFunction();
-   }
-
-   const double* Parameters() const
-   {
-      return pars;
-   }
-
-   void SetParameters(const double* p)
-   {
-      pars = p;
-   }
-
-   unsigned int NPar() const
-   {
-      return 2;
-   }
-
-   double DoParameterDerivative(const double* x, const double* p,
-                                unsigned int ipar) const
-   {
-      if ( ipar == 0 )
-         return sin(x[1]) + p[1];
-      else
-         return p[0] * x[0] + x[1] * cos(x[1]) + p[1];
-   }
-};
-```
-
-### Wrapper Functions
-
-To facilitate the user to insert their own type of function in the needed function interface, helper classes, wrapping the user interface in the
-`ROOT::Math` function interfaces are provided.
-this will avoid the user to re-implement dedicated function classes, following the code example shown in the previous paragraphs.
-
-There is one possible wrapper for every interface explained in the previous section.
-The following table indicates the wrapper for the most basic ones:
-
-
-
-
-| **Interface**|   **Function Wrapper**    |
-|------------------------------------------|------------------------|
-| `ROOT::Math::IBaseFunctionOneDim`              | `ROOT::Math::Functor1D` |
-| `ROOT::Math::IGradientFunctionOneDim`        | `ROOT::Math::GradFunctor1D` |
-| `ROOT::Math::IBaseFunctionMultiDim`             | `ROOT::Math::Functor` |
-| `ROOT::Math::IGradientFunctionMultiDim`       | `ROOT::Math::GradFunctor` |
-
-
-
-Thee functor wrapper are defined in the header file `Math/Functor.h`.
-
-#### Wrapping One Dimensional Functions
-
-The `ROOT::Math::Functor1D` is used to wrap one-dimensional functions It can wrap all the following types:
-* A free C function of type `double ()(double )`.
-* Any C++ callable object implementation `double operator()( double )`.
-* A class member function with the correct signature like `double Foo::Eval(double )`. In this case one pass the object pointer and a pointer to the member function `(&Foo::Eval)`.
-
-Example:
-
-```{.cpp}
-#include "Math/Functor.h"
-
-class MyFunction1D {
-
-public:
-
-   double operator()(double x) const {
-      return x*x;
-   }
-
-   double Eval(double x) const { return x+x; }
-};
-
-double freeFunction1D(double  x ) {
-   return 2*x;
-}
-
-int main()
-{
-   // wrapping a free function
-   ROOT::Math::Functor1D  f1(&freeFunction1D);
-
-   MyFunction1D myf1;
-
-   // wrapping a function object implementing operator()
-   ROOT::Math::Functor1D  f2(myf1);
-
-   // wrapping a class member function
-   ROOT::Math::Functor1D f3(&myf1,&MyFunction1D::Eval);
-
-   cout << f1(2) << endl;
-   cout << f2(2) << endl;
-   cout << f3(2) << endl;
-
-   return 0;
-}
-```
-
-
-#### Wrapping One Dimensional Gradient Functions
-
-The `ROOT::Math::GradFunctor1D`  class is used to wrap one-dimensional gradient functions. It can be constructed in three different ways:
-* Any object implementing both `double operator()( double)` for the function evaluation and `double Derivative(double)` for the function derivative.
-* Any object implementing any member function like `Foo::XXX(double )` for the function evaluation and any other member function like `Foo::YYY(double )` for the derivative.
-* Any two function objects implementing `double operator()( double )` . One object provides the function evaluation, the other the derivative. One or both function object can be a  free C function of
-type `double ()(double )`.
-
-#### Wrapping Multi-dimensional Functions
-
-The class `ROOT::Math::Functor`  is used to wrap in a very simple and convenient way multi-dimensional function objects. It can wrap all the following types:
-* Any C++ callable object implementing `double operator()( const double * )`.
-* A free C function of type `double ()(const double * )`.
-* A member function with the correct signature like `Foo::Eval(const double * )`. In this case one pass the object pointer and a pointer to the member function `(&Foo::Eval)`.
-
-The function dimension is required when constructing the functor.
-
-Example of using `Functor`:
-```{.cpp}
-#include "Math/Functor.h"
-
-class MyFunction {
-
-public:
-   double operator()(const double *x) const {
-      return x[0]+x[1];
-   }
-
-   double Eval(const double * x) const { return x[0]+x[1]; }
-};
-
-double freeFunction(const double * x )
-{
-   return x[0]+x[1];
-}
-
-int main()
-{
-   // test directly calling the function object
-   MyFunction myf;
-
-   // test from a free function pointer
-   ROOT::Math::Functor f1(&freeFunction,2);
-
-   // test from function object
-   ROOT::Math::Functor f2(myf,2);
-
-   // test from a member function
-   ROOT::Math::Functor f3(&myf,&MyFunction::Eval,2);
-
-   double x[] = {1,2};
-
-   cout << f1(x) << endl;
-   cout << f2(x) << endl;
-   cout << f3(x) << endl;
-
-   return 0;
-}
-```
-
-
-#### Wrapping Multi-dimensional Gradient Functions
-
-The class `ROOT::Math::GradFunctor` is used to wrap in a very C++ callable object to make gradient functions. It can be constructed in three different way:
-* From an object implementing both `double operator()( const double * )` for the function evaluation and `double Derivative(const double *, int icoord)` for the partial derivatives.
-* From an object implementing any member function like `Foo::XXX(const double *)` for the function evaluation and any member function like `Foo::XXX(const double *, int icoord)` for the partial derivatives.
-* From an function object implementing `double operator()( const double * )` for the function evaluation and another function object implementing `double operator() (const double *, int icoord)`
-for the partial derivatives.
-
-The function dimension is required when constructing the functor.
-
-#### Special case: Wrapping TF1 objects in Parametric Function interfaces
-
-In many cases, the user works with the `TF1` class. The mathematical library in ROOT provides some solutions to wrap these into the interfaces needed by other methods.
-If the desired interface to wrap is one-dimensional, the class to use is `ROOT::Math::WrappedTF1`.
-The default constructor takes a `TF1` reference as an argument, that will be wrapped with the interfaces of a `ROOT::Math::IParametricGradFunctionOneDim`.
-Example:
-```{.cpp}
-#include "TF1.h"
-#include "Math/WrappedTF1.h"
-
-int main()
-{
-
-   TF1 f("Sin Function", "sin(x)+y",0,3);
-
-   ROOT::Math::WrappedTF1 wf1(f);
-
-   cout << f(1) << endl;
-   cout << wf1(1) << endl;
-
-   return 0;
-}
-```
-
-For a TF1 defining a multidimensional function or in case we need to wrap in a multi-dimensional function interface,  the class to use is `ROOT::Math::WrappedMultiTF1`.
-Following the usual procedure, setting the `TF1` though the constructor, will wrap it into a `ROOT::Math::IParametricGradFunctionMultiDim`.
-Example:
-
-```{.cpp}
-#include "TF1.h"
-#include "Math/WrappedMultiTF1.h"
-
-int main()
-{
-
-   TF2 f("Sin Function", "sin(x) + y",0,3,0,2);
-
-   ROOT::Math::WrappedMultiTF1 wf1(f);
-
-   double x[] = {1,2};
-
-   cout << f(x) << endl;
-   cout << wf1(x) << endl;
-
-   return 0;
-}
-```
-
-
-## Numerical Integration
-
-The algorithms provided by ROOT for numerical integration are implemented following the hierarchy shown in the next image.
-`ROOT::Math::VirtualIntegrator` defines the most basic functionality while the specific behaviours for one or multiple dimensions are implemented in
-`ROOT::Math::VirtualIntegratorOneDim` and `ROOT::Math::VirtualIntegratorMultiDim`.
-These interfaces define the integrator functionality with abstract methods to set the function, to compute the integral or to set the integration tolerance.
-These methods must be implemented in the concrete classes existing for the different integration algorithms.
-The user cannot create directly these virtual integrator interfaces. He needs to create the
-`ROOT::Math::IntegratorOneDim` class for integrating one-dimensional functions and `ROOT::Math::IntegratorMultiDim` for multi-dimensional functions.
-Through the ROOT Plug-In Manager,  the user can initialize `ROOT::Math::IntegratorOneDim` or  `ROOT::Math::IntegratorMultiDim` with
-any of the concrete integration classes without dealing with them directly.
-These two classes provide the same interface as in `VirtualIntegratorOneDim` and `VirtualIntegratorMultiDim`, but with the possibility to choose in the constructor,
-which method will be used to perform the integration.
-
-The method to set the function to be integrated,  must be of the function interface type described before.
-`ROOT::Math::IBaseFunctionOneDimFunction` is used for `ROOT::Math::IBaseFunctionMultiDim` and
-The only difference between the  `ROOT::Math::IntegratorOneDim`  and `ROOT::Math::IntegratorMultiDim` resides
-in the dimensionality of that function and some specific that will be seen afterwards for the one dimensional one.
-
-![ROOT::Math Numerical Integrator classes](pictures/Integration.png)
-
-The rest of the classes shown above in the diagram are the specialized classes provided. Each one implements a different method that will be explained in detail. It is important
-to notice that the two grayed classes (the one which name starts by GSL) are part of the *MathMore* library.
-We will later show in more detail the differences between the implementations.
-
-
-### Integration of One-dimensional Functions
-
-#### Using `ROOT::Math::IntegratorOneDim`
-
-Here is a code example on how to use the  `ROOT::Math::IntegratorOneDim` class
-(note that the class is defined in the header file `Math/Integrator.h`). In this example we create
-different instance of the class using some of the available algorithms in ROOT.
-If no algorithm is specified, the default one is used. The default Integrator together with other integration options
-such as relative and absolute tolerance, can be specified using the static method of the
-`ROOT::Math::IntegratorOneDimOptions`
-
-```{.cpp}
-#include "Math/Integrator.h"
-
-const double ERRORLIMIT = 1E-3;
-
-double f(double x) {
-   return x;
-}
-
-double f2(const double * x) {
-   return x[0] + x[1];
-}
-
-
-int testIntegration1D() {
-
-   const double RESULT = 0.5;
-   int status = 0;
-
-   // set default tolerances for all integrators
-   ROOT::Math::IntegratorOneDimOptions::SetDefaultAbsTolerance(1.E-6);
-   ROOT::Math::IntegratorOneDimOptions::SetDefaultRelTolerance(1.E-6);
-
-   ROOT::Math::Functor1D wf(&f);
-   ROOT::Math::Integrator ig(ROOT::Math::IntegrationOneDim::kADAPTIVESINGULAR);
-   ig.SetFunction(wf);
-   double val = ig.Integral(0,1);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::Integrator ig2(ROOT::Math::IntegrationOneDim::kNONADAPTIVE);
-   ig2.SetFunction(wf);
-   val = ig2.Integral(0,1);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::Integrator ig3(wf, ROOT::Math::IntegrationOneDim::kADAPTIVE);
-   val = ig3.Integral(0,1);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::Integrator ig4(ROOT::Math::IntegrationOneDim::kGAUSS);
-   ig4.SetFunction(wf);
-   val = ig4.Integral(0,1);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::Integrator ig4(ROOT::Math::IntegrationOneDim::kLEGENDRE);
-   ig4.SetFunction(wf);
-   val = ig4.Integral(0,1);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   return status;
-}
-```
-
-### One-dimensional Integration Algorithms
-
-Here we provide a brief description of the different integration algorithms, which are also
-implemented as separate classes. The algorithms can be instantiated using the following enumeration values:
-
-| **Enumeration name**|   **Integrator class**    |
-|------------------------------------  |-------------------------------|
-| `ROOT::Math::IntegratorOneDim::kGAUSS`      | `ROOT::Math::GaussianIntegrator`     |
-| `ROOT::Math::IntegratorOneDim::kLEGENDRE`   | `ROOT::Math:::GausLegendreIntegrator` |
-|  `ROOT::Math::Integration::kNONADAPTIVE`           |         `ROOT::Math:::GSLIntegrator`               |
-|  `ROOT::Math::Integration::kADAPTIVE`           |         `ROOT::Math:::GSLIntegrator`               |
-|  `ROOT::Math::Integration::kADAPTIVESINGULAR`           |         `ROOT::Math:::GSLIntegrator`               |
-
-#### ROOT::Math:::GaussIntegrator
-
-It uses the most basic Gaussian integration algorithm, it uses the 8-point and the 16-point Gaussian
-quadrature approximations. It is derived from the `DGAUSS` routine of the *CERNLIB* by S. Kolbig.
-This class
-Here is an example of using directly  the `GaussIntegrator` class
-
-```{.cpp}
-#include "TF1.h"
-#include "Math/WrappedTF1.h"
-#include "Math/GaussIntegrator.h"
-
-int main()
-{
-   TF1 f("Sin Function", "sin(x)", 0, TMath::Pi());
-   ROOT::Math::WrappedTF1 wf1(f);
-
-   ROOT::Math::GaussIntegrator ig;
-
-   ig.SetFunction(wf1, false);
-   ig.SetRelTolerance(0.001);
-
-   cout << ig.Integral(0, TMath::PiOver2()) << endl;
-
-   return 0;
-}
-```
-#### ROOT::Math::GaussLegendreIntegrator
-
-This class implementes the Gauss-Legendre quadrature formulas. This sort of numerical methods requieres that the user specifies the number of intermediate function points
-used in the calculation of the integral. It will automatically determine the coordinates and weights of such points before performing the integration.
-We can use the example above, but replacing the creation of a `ROOT::Math::GaussIntegrator` object with `ROOT::Math::GaussLegendreIntegrator`.
-
-#### ROOT::Math::GSLIntegrator
-
-This is a wrapper for the *QUADPACK* integrator implemented in the GSL library. It supports several integration methods that can be chosen in construction time.
-The default type is adaptive integration with singularity applying a Gauss-Kronrod 21-point integration rule. For a detail description of the GSL methods visit the GSL user guide
-This class implements the best algorithms for numerical integration for one dimensional functions. We encourage the use it as the main option, bearing in mind that it uses code from the
-GSL library, wich is provided in the *MathMore* library of ROOT.
-
-The interface to use is the same as above. We have now the possibility to specify a different integration algorithm in the constructor of the `ROOT::Math::GSLIntegrator` class.
-```{.cpp}
-// create the adaptive integrator with the 51 point rule
-ROOT::Math::GSLIntegrator ig(ROOT::Math::Integration::kADAPTIVE, ROOT::Math::Integration::kGAUSS51);
-ig.SetRelTolerance(1.E-6);  // set relative tolerance
-ig.SetAbsTolerance(1.E-6);   // set absoulte tolerance
-```
-
-The algorithm is controlled by the given absolute and relative tolerance. The iterations are continued until the following condition is satisfied
-$$
-absErr <= max ( epsAbs, epsRel * Integral)
-$$
-Where *absErr* is an estimate of the absolute error (it can be retrieved with `GSLIntegrator::Error()`)  and *Integral* is the estimate of the function integral
-(it can be obtained with `GSLIntegrator::Result()`)
-
-The possible integration algorithm types to use with the GSLIntegrator are the following. More information is provided in the `GSL` users documentation.
-* `ROOT::Math::Integration::kNONADAPTIVE` : based on `gsl_integration_qng`. It is a non-adaptive procedure which uses fixed Gauss-Kronrod-Patterson abscissae
-to sample the integrand at a maximum of 87 points. It is provided for fast integration of smooth functions.
-* `ROOT::Math::Integration::kADAPTIVE`: based on `gsl_integration_qag`. It is an adaptiva Gauss-Kronrod integration algorithm, the integration region is divided into subintervals, and on each
-iteration the subinterval with the largest estimated error is bisected. It is possible to specify the integration rule as an extra enumeration parameter. The possible rules are
-     *  `Integration::kGAUSS15` : 15 points Gauss-Konrod rule (value = 1)
-     *  `Integration::kGAUSS21` : 21 points Gauss-Konrod rule (value = 2)
-     *  `Integration::kGAUSS31` : 31 points Gauss-Konrod rule (value = 3)
-     *  `Integration::kGAUSS41` : 41 points Gauss-Konrod rule (value = 4)
-     *  `Integration::kGAUSS51` : 51 points Gauss-Konrod rule (value = 5)
-     *  `Integration::kGAUSS61` : 61 points Gauss-Konrod rule (value = 6)
-     The higher-order rules give better accuracy for smooth functions, while lower-order rules save time when the function contains local difficulties, such as discontinuities. If no integration rule
-     is passed, the 31 points rule is used as default.
-
-*    `ROOT::Math::Integration::kADAPTIVESINGULAR`: based on `gsl_integration_qags`. It is an integration type which can be used in the case of the presence of singularities.It uses the
-       Gauss-Kronrod 21-point integration rule. This is the default algorithm
-
-Note that when using the common `ROOT::Math::IntegratorOneDIm` class the enumeration type defining the algorithm must be defined in the namespace `ROOT::Math::IntegrationOneDim` (to distinguish from
-the multi-dimensional case) and  the rule enumeration (or its corresponding integer) can be passed in the constructor of the `ROOT::Math::IntegratorOneDIm`.
-
-### Multi-dimensional Integration
-
-The multi-dimensional integration algorithm should be applied to functions with dimension larger than one.
-Adaptive multi-dimensional integration works for low function dimension, while MC integration can be applied to higher dimensions.
-
-#### Using `ROOT::Math::IntegratorMultiDim`
-
-Here is a code example on how to use the  `ROOT::Math::IntegratorOneDim` class
-(note that the class is defined in the header file `Math/Integrator.h`). In this example we create
-different instance of the class using some of the available algorithms in ROOT.
-
-```{.cpp}
-#include "Math/IntegratorMultiDim.h"
-#include "Math/Functor.h"
-
-
-double f2(const double * x) {
-   return x[0] + x[1];
-}
-
-int testIntegrationMultiDim() {
-
-   const double RESULT = 1.0;
-   const double ERRORLIMIT = 1E-3;
-   int status = 0;
-
-   ROOT::Math::Functor wf(&f2,2);
-   double a[2] = {0,0};
-   double b[2] = {1,1};
-
-   ROOT::Math::IntegratorMultiDim ig(ROOT::Math::IntegrationMultiDim::kADAPTIVE);
-   ig.SetFunction(wf);
-   double val = ig.Integral(a,b);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::IntegratorMultiDim ig2(ROOT::Math::IntegrationMultiDim::kVEGAS);
-   ig2.SetFunction(wf);
-   val = ig2.Integral(a,b);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::IntegratorMultiDim ig3(wf,ROOT::Math::IntegrationMultiDim::kPLAIN);
-   val = ig3.Integral(a,b);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   ROOT::Math::IntegratorMultiDim ig4(wf,ROOT::Math::IntegrationMultiDim::kMISER);
-   val = ig4.Integral(a,b);
-   std::cout << "integral result is " << val << std::endl;
-   status += std::fabs(val-RESULT) > ERRORLIMIT;
-
-   return status;
-}
-```
-
-#### Multi-dimensions Integration Algorithms
-
-Here is the types, that can be specified as enumeration and the corresponding classes
-
-| **Enumeration name**|   **Integrator class**    |
-|------------------------------------  |-------------------------------|
-| `ROOT::Math::IntegratorMultiDim::kADAPTIVE`      | `ROOT::Math::AdaptiveIntegratorMultiDim`     |
-| `ROOT::Math::IntegratorMultiDim::kVEGAS`   | `ROOT::Math:::GSLMCIntegrator` |
-| `ROOT::Math::IntegratorMultiDim::kMISER`   | `ROOT::Math:::GSLMCIntegrator` |
-| `ROOT::Math::IntegratorMultiDim::kPLAIN`   | `ROOT::Math:::GSLMCIntegrator` |
-
-The control parameters for the integration algorithms can be specified using the
-`ROOT::Math::IntegratorMultiDimOptions` class. Static methods are provided to change the default values.
-It is possible to print the list of default control parameters using the  `ROOT::Math::IntegratorMultiDimOptions::Print` function.
-Example:
-```{.cpp}
-ROOT::Math::IntegratorMultiDimOptions opt;
-opt.Print();
-          Integrator Type :        ADAPTIVE
-       Absolute tolerance :           1e-09
-       Relative tolerance :           1e-09
-           Workspace size :          100000
-     (max) function calls :          100000
-```
-Depending on the algorithm, some of the control parameters might have no effect.
-
-#### `ROOT::Math::AdaptiveIntegratorMultiDim`
-
-This class implements an adaptive quadrature integration method for multi dimensional functions. It is described in this paper
-*Genz, A.A. Malik, An adaptive algorithm for numerical integration over an N-dimensional rectangular region, J. Comput. Appl. Math. 6 (1980) 295-302*.
-It is part of the *MathCore* library.
-The user can control the relative and absolute tolerance and the maximum allowed number of function evaluation.
-
-
-#### `ROOT::Math::GSLMCIntegrator`
-
-It is a class for performing numerical integration of a multidimensional function. It uses the numerical integration algorithms of GSL, which reimplements the algorithms used
-in the QUADPACK, a numerical integration package written in Fortran. Plain MC, MISER and VEGAS integration algorithms are supported for integration over finite (hypercubic) ranges.
-For a detail description of the GSL methods visit the GSL users guide.
-Specific configuration options (documented in the GSL user guide) for the `ROOT::Math::GSLMCIntegration` can be set directly in the class, or when using it via the `ROOT::Math::IntegratorMultiDim`
-interface, can be defined using the `ROOT::Math::IntegratorMultiDimOptions`.
-
-
-
-## Function Derivation
-
-There are in ROOT only two classes to perform numerical derivation. One of them is in the MathCore library while the other is in the MathMore wrapping an integration function from the GSL library.
-* RichardsonDerivator: Implements the Richardson method for numerical integration. It can calculate up to the third derivative of a function.
-* GSLDerivator of *MathMore* based on GSL.
-
-## Numerical Minimization
-
-The algorithms provided by ROOT for numerical integration are implemented following the hierarchy shown in the next image. The left branch of classes are used for one dimensional minimization, while
-the right one is used for multidimensional minimization. In the case of multidimensional minimization we have also the classes `TMinuitMinimizer` implemented using `TMinuit`, `TFumiliMinimizer`
-implemented using `TFumili` for least square or likelihood minimizations.
-We encourage the use of the GSL algorithms for one dimensional minimization and `Minuit2` (or the old version`Minuit`) for multi dimensional minimization.
-
-![Numerical Minimization classes](pictures/Minimization.png)
-
-
-### One-Dimensional Minimization
-
-These algorithms are for finding the minimum of a one-dimensional minimization function.
-The function to minimize must be given to the class implementing the algorithm as a
-`ROOT::Math::IBaseFunctionOneDim` object.
-The algorithms supported are only bracketing algorithm which do not use derivatives information.
-
-
-Two classes exist. One in the *MathCore* library implementing the Brent method (not using the derivatives)
-and one in the *MathMore* library implementing several different methods, using in some case the derivatives.
-
-#### `ROOT::Math::BrentMinimizer1D`
-
-This class implements the Brent method to minimize one-dimensional function.
-An interval containing the function minimum must be provided.
-Here is an example where we define the function to minimize as a *lambda* function
-(requires C++11). The function to minimize must be given to the class implementing the algorithm as a
-`ROOT::Math::IBaseFunctionOneDim` object.
-
-```{.cpp}
-  ROOT::Math::Functor1D func( [](double x){ return 1 + -4*x + 1*x*x; } );
-
-   ROOT::Math::BrentMinimizer1D bm;
-   bm.SetFunction(func, -10,10);
-   bm.Minimize(10,0,0);
-   cout << "Minimum: f(" << bm.XMinimum() << ") = " <<bm.FValMinimum() << endl;
-```
-
-Note that when setting the function to minimize, one needs to provide the  interval range to find the minimum.
-In the `Minimize` call, the maximum number of function calls, the relative and absolute tolerance must be provided.
-
-#### `ROOT::Math::GSLMInimizer1D`
-
-This class wraps two different methods from the GSL.
-The algorithms which can be chosen at construction time are *GOLDENSECTION*, which is the simplest method
-but the slowest and *BRENT* (the default one) which combines the golden section with a parabolic interpolation.
-The algorithm can be chosen as a different enumeration in the constructor:
-* `ROOT::Math::Minim1D::kBRENT` for the Brent algorithm (default)
-* `ROOT::Math::Minim1D::kGOLDENSECTION` for the golden section algorithm
-
-```{.cpp}
- // this makes class with the default Brent algorithm
- ROOT::Math::GSLMinimizer1D minBrent;
-  // this make the class with the Golden Section algorithm
-   ROOT::Math::GSLMinimizer1D minGold(ROOT::Math::Minim1D::kGOLDENSECTION);
-```
-
-The interface to set the function and to minimize is the same as in the case of the `BrentMinimizer1D`.
-
-#### Using the TF1 class
-
-It is possible to perform the one-dimensional minimization/maximization of a function by using directly the  function class in ROOT, `TF1` of the *Hist* library.
-The minmization is implemented in `TF1` using the BrentMInimizer1D and available with the class member functions
-* `TF1::GetMinimum`/`TF1::GetMaximum` to find the function minimum/maximum value
-* `TF1::GetMinimumX`/`TF1::GetMaximumX` to find the x value corresponding at the function minimum.
-
-The interval to search for the minimum (the default is the `TF1` range),  tolerance and maximum iterations can be provided as optional parameters of the
-`TF1::GetMinimum/Maximum` functions.
-
-
-### Multi-Dimensional Minimization
-
-All the algorithms for multi-dimensional minimization are implementing the `ROOT::Math::Minimizer`
-interface and they can be used in the same way and one can switch between minimizer at run-time.
-The minimizer concrete class can be in different ROOT libraries and they can be instantiate using the ROOT
-plug-in manager.
-More information on multi-dimensional minimization is provided in the Fitting Histogram chapter.
-
-## ROOT Finder Algorithms
-
-The function must be given to the class implementing the algorithm as a
-`ROOT::Math::IBaseFunctionOneDim` object.
-Some of the algorithm requires the derivatives of the function.
-In that case a `ROOT::Math::IGradientFunctionOneDim` object must be provided.
-
-
-
-
-
-
-## Generic Vectors for 2, 3 and 4 Dimensions (GenVector)
-
-
-`GenVector` is a package intended to represent vectors and their
-operations and transformations, such as rotations and Lorentz
-transformations, in 3 and 4 dimensions. The 3D space is used to describe
-the geometry vectors and points, while the 4D space-time is used for
-physics vectors representing relativistic particles. These 3D and 4D
-vectors are different from vectors of the linear algebra package, which
-describe generic N-dimensional vectors. Similar functionality is
-currently provided by the CLHEP <Vector> and <Geometry> packages and the
-ROOT Physics vector classes (See "Physics Vectors"). It also re-uses
-concepts and ideas from the CMS
-[Common Vector package](Common Vector package). In contrast to CLHEP or
-the ROOT physics libraries, `GenVector` provides class templates for
-modeling the vectors. The user can control how the vector is internally
-represented. This is expressed by a choice of coordinate system, which
-is supplied as a template parameter when the vector is constructed.
-Furthermore, each coordinate system is itself a template, so that the
-user can specify the underlying scalar type.
-
-The `GenVector` classes do not inherit from **`TObject`**, therefore
-cannot be used as in the case of the physics vector classes in ROOT
-collections.
-
-In addition, to optimize performances, no virtual destructors are
-provided. In the following paragraphs, the main characteristics of
-`GenVector` are described. A more detailed description of all the
-`GenVector` classes is available also at
-<http://seal.cern.ch/documents/mathlib/GenVector.pdf>
-
-### Main Characteristics
-
-
-#### Optimal Runtime Performances
-
-We try to minimize any overhead in the run-time performance. We have
-deliberately avoided the use of any virtual function and even virtual
-destructors in the classes. In addition, as much as possible functions
-are defined as inline. For this reason, we have chosen to use template
-classes to implement the `GenVector` concepts instead of abstract or
-base classes and virtual functions. It is then recommended to avoid
-using the `GenVector` classes polymorphically and developing classes
-inheriting from them.
-
-#### Points and Vector Concept
-
-Mathematically vectors and points are two distinct concepts. They have
-different transformations, as vectors only rotate while points rotate
-and translate. You can add two vectors but not two points and the
-difference between two points is a vector. We then distinguish for the 3
-dimensional case, between points and vectors, modeling them with
-different classes:
-
--   `ROOT::Math::`**`DisplacementVector2D`** and
-    `ROOT::Math::`**`DisplacementVector3D`** template classes describing
-    2 and 3 component direction and magnitude vectors, not rooted at any
-    particular point;
-
--   `ROOT::Math::`**`PositionVector2D`** and
-    `ROOT::Math::`**`PositionVector3D`** template classes modeling the
-    points in 2 and 3 dimensions.
-
-For the 4D space-time vectors, we use the same class to model them,
-`ROOT::Math::`**`LorentzVector`**, since we have recognized a limited
-need for modeling the functionality of a 4D point.
-
-#### Generic Coordinate System
-
-The vector classes are based on a generic type of coordinate system,
-expressed as a template parameter of the class. Various classes exist to
-describe the various coordinates systems:
-
-2D coordinate system classes:
-
--   **`ROOT::Math::Cartesian2D`**, based on (`x,y`);
-
--   **`ROOT::Math::Polar2D`**, based on (`r,phi`);
-
-3D coordinate system classes:
-
--   **`ROOT::Math::Cartesian3D`**, based on (`x,y,z`);
-
--   **`ROOT::Math::Polar3D`**, based on (`r,theta,phi`);
-
--   **`ROOT::Math::Cylindrical3D`**, based on (`rho,z,phi`)
-
--   **`ROOT::Math::CylindricalEta3D`**, based on (`rho,eta,phi`), where
-    `eta` is the pseudo-rapidity;
-
-4D coordinate system classes:
-
--   **`ROOT::Math::PxPyPzE4D`**, based on based on (`px,py,pz,E`);
-
--   **`ROOT::Math::PxPyPzM4D`**, based on based on (`px,py,pz,M`);
-
--   **`ROOT::Math::PtEtaPhiE4D`**, based on based on (`pt,eta,phi,E`);
-
--   **`ROOT::Math::PtEtaPhiM4D`**, based on based on (`pt,eta,phi,M`);
-
-Users can define the vectors according to the coordinate type, which is
-the most efficient for their use. Transformations between the various
-coordinate systems are available through copy constructors or the
-assignment (=) operator. For maximum flexibility and minimize memory
-allocation, the coordinate system classes are templated on the scalar
-type. To avoid exposing templated parameter to the users, typedefs are
-defined for all types of vectors based on doubles. See in the examples
-for all the possible types of vector classes, which can be constructed
-by users with the available coordinate system types.
-
-#### Coordinate System Tag
-
-The 2D and 3D points and vector classes can be associated to a tag
-defining the coordinate system. This can be used to distinguish between
-vectors of different coordinate systems like global or local vectors.
-The coordinate system tag is a template parameter of the
-**`ROOT::Math::`**`DisplacementVector3D` and
-`ROOT::Math::PositionVector3D` (and also for 2D classes). A default tag
-exists for users who do not need this functionality,
-`ROOT::Math::DefaultCoordinateSystemTag`.
-
-#### Transformations
-
-The transformations are modeled using simple (non-template) classes,
-using double as the scalar type to avoid too large numerical errors. The
-transformations are grouped in rotations (in 3 dimensions), Lorentz
-transformations and Poincare transformations, which are
-translation`/`rotation combinations. Each group has several members
-which may model physically equivalent transformations but with different
-internal representations. Transformation classes can operate on all type
-of vectors by using the operator `() `or the operator `*` and the
-transformations can be combined via the operator `*`. The available
-transformations are:
-
-- 3D rotation classes
-
--   rotation described by a 3x3 matrix (**`ROOT::Math::Rotation3D`**)
-
--   rotation described by Euler angles (**`ROOT::Math::EulerAngles`**)
-
--   rotation described by a direction axis and an angle
-    (**`ROOT::Math::AxisAngle`**)
-
--   rotation described by a quaternion (**`ROOT::Math::Quaternion`**)
-
--   optimized rotation around `x` (**`ROOT::Math::RotationX`**), `y`
-    (**`ROOT::Math::RotationY`**) and `z` (**`ROOT::Math::RotationZ`**)
-    and described by just one angle.
-
-- 3D transformation: we describe the transformations defined as a
-composition between a rotation and a translation using the class
-**`ROOT::Math::Transform3D`**. It is important to note that
-transformations act differently on vectors and points. The vectors only
-rotate, therefore when applying a transformation (rotation +
-translation) on a vector, only the rotation operates while the
-translation has no effect. The **`Transform3D`** class interface is
-similar to the one used in the CLHEP Geometry package (class
-<HepGeom::Transform3D>).
-
-- Lorentz rotation:
-
--   generic Lorentz rotation described by a `4x4` matrix containing a 3D
-    rotation part and a boost part (class
-    **`ROOT::Math::LorentzRotation`**)
-
--   a pure boost in an arbitrary direction and described by a 4x4
-    symmetric matrix or 10 numbers (class **`ROOT::Math::Boost`**)
-
--   boost along the axis:` x `(**`ROOT::Math::BoostX`**),
-    `y `(**`ROOT::Math::BoostY`**) and `z `(**`ROOT::Math::BoostZ`**).
-
-#### Minimal Vector Classes Interface
-
-We have tried to keep the interface to a minimal level by:
-
--   Avoiding methods that provide the same functionality but use
-    different names (like `getX()` and `x()`).
-
--   Minimizing the number of setter methods, avoiding methods, which can
-    be ambiguous and can set the vector classes in an inconsistent
-    state. We provide only methods which set all the coordinates at the
-    same time or set only the coordinates on which the vector is based,
-    for example `SetX()` for a Cartesian vector. We then enforce the use
-    of transformations as rotations or translations (additions) for
-    modifying the vector contents.
-
--   The majority of the functionality, which is present in the CLHEP
-    package, involving operations on two vectors, is moved in separated
-    helper functions (see `ROOT::Math::VectorUtil`). This has the
-    advantage that the basic interface will remain more stable with time
-    while additional functions can be added easily.
-
-#### Naming Convention
-
-As part of ROOT, the `GenVector` package adheres to the prescribed ROOT
-naming convention, with some (approved) exceptions, as described here:
-
--   Every class and function is in the **`ROOT::Math`** namespace.
-
--   Member function names start with upper-case letter, apart some
-    exceptions (see the next section about CLHEP compatibility).
-
-#### Compatibility with CLHEP Vector Classes
-
--   For backward compatibility with CLHEP the vector classes can be
-    constructed from a CLHEP `HepVector` or **`HepLorentzVector`**, by
-    using a template constructor, which requires only that the classes
-    implement the accessors` x()`, `y()`, and `z()` (and `t()` for the
-    4D).
-
--   We provide vector member function with the same naming convention as
-    CLHEP for the most used functions like `x()`, `y()` and `z()`.
-
-#### Connection to Linear Algebra Package
-
-In some use cases, like in track reconstruction, it is needed to use the
-content of the vector and rotation classes in conjunction with linear
-algebra operations. We prefer to avoid any direct dependency to any
-linear algebra package. However, we provide some hooks to convert to and
-from linear algebra classes. The vector and the transformation classes
-have methods which allow to get and set their data members (like
-`SetCoordinates` and `GetCoordinates`) passing either a generic iterator
-or a pointer to a contiguous set of data, like a C array. This allows an
-easy connection with the linear algebra package, which in turn, allows
-creation of matrices using C arrays (like the ROOT **`TMatrix`**
-classes) or iterators (`SMatrix` classes). Multiplication between linear
-algebra matrices and `GenVector` vectors is possible by using the
-template free functions `ROOT::Math::VectorUtil::Mult`. This function
-works for any linear algebra matrix, which implements the operator
-(`i,j`) and with first matrix element at `i=j=0`.
-
-### Example: 3D Vector Classes
-
-
-To avoid exposing template parameter to the users, typedef's are defined
-for all types of vectors based on double's and float's. To use them, one
-must include the header file `Math/Vector3D.h`. The following typedef's,
-defined in the header file `Math/Vector3Dfwd.h`, are available for the
-different instantiations of the template class
-`ROOT::Math::`**`DisplacementVector3D`**:
-
--   `ROOT::Math::`**`XYZVector`** vector based on `x,y,z` coordinates
-    (Cartesian) in double precision
-
--   `ROOT::Math::`**`XYZVectorF`** vector based on `x,y,z` coordinates
-    (Cartesian) in float precision
-
--   `ROOT::Math::`**`Polar3DVector`** vector based on `r,theta,phi`
-    coordinates (polar) in double precision
-
--   `ROOT::Math::`**`Polar3DVectorF`** vector based on `r,theta,phi`
-    coordinates (polar) in float precision
-
--   `ROOT::Math::`**`RhoZPhiVector`** vector based on `rho,z,phi`
-    coordinates (cylindrical) in double precision
-
--   `ROOT::Math::`**`RhoZPhiVectorF`** vector based on `rho,z,phi`
-    coordinates (cylindrical) in float precision
-
--   `ROOT::Math::`**`RhoEtaPhiVector`** vector based on `rho,eta,phi`
-    coordinates (cylindrical using `eta` instead of `z`) in double
-    precision
-
--   `ROOT::Math::`**`RhoEtaPhiVectorF`** vector based on `rho,eta,phi`
-    coordinates (cylindrical using `eta` instead of `z`) in float
-    precision
-
-#### Constructors and Assignment
-
-The following declarations are available:
-
-``` {.cpp}
-XYZVector       v1;             //an empty vector (x=0, y=0, z=0)
-XYZVector       v2(1,2,3);      //vector with x=1, y=2, z=3;
-Polar3DVector   v3(1,PI/2,PI);  //vector with r=1, theta=PI/2, phi=PI
-RhoEtaPHiVector v4(1,2, PI);    //vector with rho=1, eta=2, phi=PI
-```
-
-Note that each vector type is constructed by passing its coordinate
-representation, so a `XYZVector(1,2,3)` is different from a
-`Polar3DVector(1,2,3)`. In addition, the vector classes can be
-constructed by any vector, which implements the accessors `x()`, `y()`
-and `z()`. This can be another 3D vector based on a different coordinate
-system type. It can be even any vector of a different package, like the
-CLHEP **`HepThreeVector`** that implements the required signature.
-
-``` {.cpp}
-   XYZVector    v1(1,2,3);
-   RhoEtaPhiVector    r2(v1);
-   CLHEP::HepThreeVector  q(1,2,3);
-   XYZVector    v3(q);
-```
-
-#### Coordinate Accessors
-
-All coordinate accessors are available through the class
-`ROOT::Math::`**`DisplacementVector3D`**:
-
-``` {.cpp}
-   //returns cartesian components for the cartesian vector v1
-   v1.X(); v1.Y(); v1.Z();
-   //returns cylindrical components for the cartesian vector v1
-   v1.Rho(); v1.Eta(); v1.Phi();
-   //returns cartesian components for the cylindrical vector r2
-   r2.X(); r2.Y(); r2.Z()
-```
-
-In addition, all the 3 coordinates of the vector can be retrieved with
-the `GetCoordinates` method:
-
-``` {.cpp}
-   double d[3];
-   //fill d array with (x,y,z) components of v1
-   v1.GetCoordinates(d);
-   //fill d array with (r,eta,phi) components of r2
-   r2.GetCoordinates(d);
-   std::vector vc(3);
-   //fill std::vector with (x,y,z) components of v1
-   v1.GetCoordinates(vc.begin(),vc.end());
-```
-
-See the reference documentation of
-`ROOT::Math::`**`DisplacementVector3D`** for more details on all the
-coordinate accessors.
-
-#### Setter Methods
-
-One can set only all the three coordinates via:
-
-``` {.cpp}
-   v1.SetCoordinates(c1,c2,c3);  // (x,y,z) for a XYZVector
-   r2.SetCoordinates(c1,c2,c3);  // r,theta,phi for a Polar3DVector
-   r2.SetXYZ(x,y,z);   // 3 cartesian components for Polar3DVector
-```
-
-Single coordinate setter methods are available for the basic vector
-coordinates, like `SetX()` for a **`XYZVector`** or `SetR()` for a polar
-vector. Attempting to do a `SetX()` on a polar vector will not compile.
-
-``` {.cpp}
-   XYZVector v1;
-   v1.SetX(1);   //OK setting x for a Cartesian vector
-   Polar3DVector v2;
-   v2.SetX(1);   //ERROR: cannot set X for a Polar vector.
-   //Method will not compile
-   v2.SetR(1);   //OK setting r for a Polar vector
-```
-
-In addition, there are setter methods from C arrays or iterator
-
-``` {.cpp}
-   double d[3] = {1.,2.,3.};
-   XYZVector v;
-   // set (x,y,z) components of v using values from d
-   v.SetCoordinates(d);
-```
-
-or, for example, from an `std::vector` using the iterator
-
-``` {.cpp}
-   std::vector w(3);
-   // set (x,y,z) components of v using values from w
-   v.SetCoordinates(w.begin(),w.end());
-```
-
-#### Arithmetic Operations
-
-The following operations are possible between vector classes, even of
-different coordinate system types: (`v1,v2` are any type of
-**`ROOT::Math::DisplacementVector3D`** classes, `v3` is the same type
-of `v1`; `a` is a scalar value)
-
-``` {.cpp}
-   v1 += v2;
-   v1 -= v2;
-   v1 = - v2;
-   v1 *= a;
-   v1 /= a;
-   v2 = a * v1;
-   v2 = v1 / a;
-   v2 = v1 * a;
-   v3 = v1 + v2;
-   v3 = v1 - v2;
-```
-
-#### Comparison
-
-For `v1` and `v2` of the same type (same coordinate system and same
-scalar type):
-
-``` {.cpp}
-   v1 == v2;
-   v1 != v2;
-```
-
-#### Dot and Cross Product
-
-We support the dot and cross products, through the `Dot()` and `Cross()`
-method, with any vector (`q`) implementing `x()`, `y()` and `z()`.
-
-``` {.cpp}
-   XYZVector v1(x,y,z);
-   double s = v1.Dot(q);
-   XYZVector v2 = v1.Cross(q);
-```
-
-Note that the multiplication between two vectors using the operator `*`
-is not supported because it is ambiguous.
-
-> [!note]
-> For the vectors using the 4D coordinate systems based on mass instead of energy (such as **`ROOT::Math::PxPyPzM4D`** or **`ROOT::Math::PtEtaPhiM4D`**) the unary operator `-` (negation) doesn't perform a 4-vector negation. Instead, it negates only the spatial components, which might result in unintuive behaviours (for instance, for PxPyPzM4D coordinate system, $\textbf{v}+ \left(-\textbf{v}\right) \neq \textbf{v} -\textbf{v}$).
-
-#### Other Methods
-
-``` {.cpp}
-   XYZVector u = v1.Unit(); //return unit vector parallel to v1
-```
-
-### Example: 3D Point Classes
-
-
-To use all possible types of 3D points one must include the header file
-`Math/Point3D.h`. The following typedef's defined in the header file
-`Math/Point3Dfwd.h`, are available for different instantiations of the
-template class **`ROOT::Math`**`::`**`PositionVector3D`**:
-
--   `ROOT::Math::`**`XYZPoint`** point based on `x`, `y`, `z`
-    coordinates (Cartesian) in double precision
-
--   `ROOT::Math::`**`XYZPointF`** point based on `x`, `y`, `z`
-    coordinates (Cartesian) in float precision
-
--   `ROOT::Math::`**`Polar3DPoint`** point based on `r`, `theta`, `phi`
-    coordinates (polar) in double precision
-
--   `ROOT::Math::`**`Polar3DPointF`** point based on `r`, `theta`, `phi`
-    coordinates (polar) in float precision
-
--   `ROOT::Math::`**`RhoZPhiPoint`** point based on `rho`, `z`, `phi`
-    coordinates (cylindrical using `z`) in double precision
-
--   `ROOT::Math::`**`RhoZPhiPointF`** point based on `rho`, `z`, `phi`
-    coordinates (cylindrical using `z`) in float precision
-
--   `ROOT::Math::`**`RhoEtaPhiPoint`** point based on `rho`, `eta`,
-    `phi` coordinates (cylindrical using eta instead of `z`) in double
-    precision
-
--   `ROOT::Math::`**`RhoEtaPhiPointF`** point based on `rho`, `eta`,
-    `phi` coordinates (cylindrical using eta instead of `z`) in float
-    precision
-
-#### Constructors and Assignment
-
-The following declarations are available:
-
-``` {.cpp}
-   XYZPoint         p1;             //an empty vector (x=0, y=0, z=0)
-   XYZPoint         p2(1,2,3);      //
-```
-
-Note that each point type is constructed by passing its coordinate
-representation, so a `XYZPoint(1,2,3)` is different from a
-`Polar3DPoint(1,2,3)`. In addition the point classes can be constructed
-by any vector, which implements the accessors `x()`, `y()` and `z()`.
-This can be another 3D point based on a different coordinate system type
-or even any vector of a different package, like the CLHEP
-**`HepThreePoint`** that implements the required signatures.
-
-``` {.cpp}
-   XYZPoint             p1(1,2,3);
-   RhoEtaPHiPoint       r2(v1);
-   CLHEP::HepThreePoint q(1,2,3);
-   XYZPoint             p3(q);
-```
-
-#### Coordinate Accessors and Setter Methods
-
-For the points classes we have the same getter and setter methods as for
-the vector classes. See "Example: 3D Vector Classes".
-
-#### Point-Vector Operations
-
-The following operations are possible between points and vector classes:
-(`p1`, `p2` and `p3` are instantiations of the
-`ROOT::Math::`**`PositionVector3D`** objects with `p1` and `p3` of the
-same type; `v1` and `v2` are `ROOT::Math::`**`DisplacementVector3D`**
-objects).
-
-``` {.cpp}
-   p1 += v1;
-   p1 -= v1;
-   p3 = p1 + v1;    // p1 and p3 are the same type
-   p3 = v1 + p1;    // p3 is based on the same coordinate system as v1
-   p3 = p1 - v1;
-   p3 = v1 - p1;
-   v2 = p1 - p2;    // difference between points returns a vector v2
-                    // based on the same coordinate system as p1
-```
-
-Note that the addition between two points is **NOT** possible and the
-difference between points returns a vector.
-
-#### Other Operations
-
-Exactly as for the 3D Vectors, the following operations are allowed:
-
--   comparison of points
-
--   scaling and division of points with a scalar
-
--   dot and cross product with any type of vector
-
-### Example: LorentzVector Classes
-
-
-As in the 3D case, typedef's are defined for user convenience. and can
-be used by including the header file `Math/Vector4D.h`. The following
-typedef's, defined in the header file `Math/Vector4Dfwd.h`, are
-available for the different instantiations of the template class
-**`ROOT::Math::LorentzVector`**:
-
--   `ROOT::Math::`**`XYZTVector`** vector based on `x`, `y`, `z`, `t`
-    coordinates (Cartesian) in double precision
-
--   `ROOT::Math::`**`XYZTVectorF`** vector based on `x`, `y`, `z`, `t`
-    coordinates (Cartesian) in float precision
-
--   `ROOT::Math::`**`PtEtaPhiEVector`** vector based on `pt(rho)`,
-    `eta`, `phi` and `E(t)` coordinates in double precision
-
--   `ROOT::Math::`**`PtEtaPhiMVector`** vector based on `pt(rho)`,
-    `eta`, `phi` and `M(t)` coordinates in double precision
-
--   `ROOT::Math::`**`PxPyPzMVector`** vector based on `px`, `py`, `pz`
-    and `M(mass)` coordinates in double precision
-
-The metric used for all the LorentzVector is (`-,-,-,+`) .
-
-#### Constructors and Assignment
-
-The following declarations are available:
-
-``` {.cpp}
-   // create an empty vector (x=0, y=0, z=0, t=0)
-   XYZTVector      v1;
-   // vector with x=1, y=2, z=3, t=4
-   XYZTVector      v2(1,2,3,4);
-   // vector with pt=1, eta=2, phi=PI, E=5
-   PtEtaPhiEVector v3(1,2,PI,5);
-```
-
-Note that each type of vector is constructed by passing its coordinate
-representation, so a **`XYZTVector`**`(1,2,3,4)` is different from a
-`PtEtaPhiEVector(1,2,3,4)`. In addition, the Vector classes can be
-constructed by any vector, which implements the accessors `x()`, `y()`,
-`z()` and `t()`.
-
-This can be another `ROOT::Math::`**`LorentzVector`** based on a
-different coordinate system or any vector of a different package, like
-the CLHEP **`HepLorentzVector`** that implements the required signature.
-
-``` {.cpp}
-   XYZTVector              v1(1,2,3,4);
-   PtEtaPhiEVector         v2(v1);
-   CLHEP::HepLorentzVector q(1,2,3,4);
-   XYZTVector              v3(q);
-```
-
-#### Coordinate Accessors
-
-All the same coordinate accessors are available through the interface of
-`ROOT::Math::`**`LorentzVector`**. For example:
-
-``` {.cpp}
-   //returns cartesian components for the cartesian vector v1
-   v1.X(); v1.X(); v1.Z(); v1.T();
-   //returns cartesian components for the cylindrical vector v2
-   v2.Px(); v2.Py(); v2.Pz(); v2.E();
-   //returns other components for the cartesian vector v1
-   v1.Pt(); v1.Eta(); v1.Phi(); v1.M()
-```
-
-In addition, all 4 vector coordinates can be retrieved with the
-`GetCoordinates` method:
-
-``` {.cpp}
-   double d[4];
-   //fill d array with (x,y,z,t) components of v1
-   v1.GetCoordinates(d);
-   //fill d array with (pt,eta,phi,e) components of v2
-   v2.GetCoordinates(d);
-   std::vector w(4);
-   //fill std::vector with (x,y,z,t)
-   v1.GetCoordinates(w.begin(),w.end());
-   //components of v1
-```
-
-To get information on all the coordinate accessors see the
-`ROOT::Math::`**`LorentzVector`** reference documentation.
-
-#### Setter Methods
-
-One can set only all the three coordinates via:
-
-``` {.cpp}
-   //sets the (x,y,z,t) for a XYZTVector
-   v1.SetCoordinates(c1,c2,c3,c4);
-   //sets pt,eta,phi,e for a PtEtaPhiEVector
-   v2.SetCoordinates(c1,c2,c3,c4);
-   //sets cartesian components for PtEtaPhiEVector
-   v2.SetXYZ(x,y,z,t);
-```
-
-Single coordinate setter methods are available for the basic vector
-coordinates, like `SetX()` for a `XYZTVector` or `SetPt()` for a
-**`PtEtaPhiEVector`**. Attempting to do a `SetX()` on a non-Cartesian
-vector will not compile.
-
-``` {.cpp}
-   XYZTVector      v1;
-   v1.SetX(1);  //OK setting x for a cartesian vector
-   PtEtaPhiEVector v2;
-   v2.SetX(1);  //ERROR: cannot set X for a non-cartesian
-                //vector. Method will not compile.
-   v2.SetR(1)   // OK setting Pt for a  PtEtaPhiEVector vector
-```
-
-In addition, there are setter methods from C arrays or iterators.
-
-``` {.cpp}
-   double d[4] = {1.,2.,3.,4.};
-   XYZTVector v;
-   //set (x,y,z,t) components of v using values from d
-   v.SetCoordinates(d);
-```
-
-or for example from an `std::vector `using the iterators
-
-``` {.cpp}
-   std::vector w(4);
-   //set (x,y,z,t) components of v using values from w
-   v.SetCoordinates(w.begin(),w.end());
-```
-
-#### Arithmetic Operations
-
-The following operations are possible between Lorentz vectors classes,
-even of different coordinate system types: (`v` and` w` are two Lorentz
-vector of the same type, `q `is a generic Lorentz vector implementing
-`x()`, `y()`, `z()` and `t()`, and `a` is a generic scalar type: double,
-float, int, etc.) .
-
-``` {.cpp}
-   v += q;
-   v -= q;
-   v  = -q;
-   v *= a;
-   v /= a;
-   w = v + q;
-   w = v - q;
-   w = v * a;
-   w = a * v;
-   w = v / a;
-```
-
-#### Comparison
-
-``` {.cpp}
-   v == w;
-   v != w;
-```
-
-#### Other Methods
-
-``` {.cpp}
-   a =  v.Dot(q); //dot product in metric(+,+,+,-) of 2 LorentzVectors
-   XYZVector s = v.Vect() //return the spatial components (x,y,z)
-   v.Beta(); //return beta and gamma value (vector must
-   v.Gamma() // be time-like otherwise result is meaningless)
-   XYZVector b = v.BoostToCM(); //return boost vector which will bring
-                                //the Vector in its mas frame (P=0)
-```
-
-### Example: Vector Transformations
-
-
-Transformation classes are grouped in rotations (in three dimensions),
-Lorentz transformations and Poincaré transformations, which are
-translation`/`rotation combinations. Each group has several members
-which may model physically equivalent transformations but with
-different internal representations. All the classes are non-template
-and use double precision as the scalar type. The following types of
-transformation classes are defined:
-
-3D rotations:
-
--   `ROOT::Math::`**`Rotation3D`**, rotation described by a 3x3 matrix
-    of doubles
-
--   `ROOT::Math::`**`EulerAngles`** rotation described by the three
-    Euler angles (`phi`, `theta` and `psi`) following the
-    [GoldStein definition](GoldStein definition).
-
--   **`ROOT::Math::RotationZYX`** rotation described by three angles
-    defining a rotation first along the `Z` axis, then along the rotated
-    `Y'` axis and then along the rotated `X''` axis.
-
--   `ROOT::Math::`**`AxisAngle`**, rotation described by a vector (axis)
-    and an angle
-
--   `ROOT::Math::`**`Quaternion`**, rotation described by a quaternion
-    (4 numbers)
-
--   `ROOT::Math::`**`RotationX`**, specialized rotation along the X axis
-
--   `ROOT::Math::`**`RotationY`**, specialized rotation along the Y axis
-
--   `ROOT::Math::`**`RotationZ`**, specialized rotation along the Z axis
-
-3D transformations (rotations + translations)
-
--   `ROOT::Math::`**`Transform3D`**, (rotations and then translation)
-    described by a 3x4 matrix (12 double numbers)
-
--   **`ROOT::Math::Translation3D`** (only translation) described by a 3D
-    Vector
-
-Lorentz rotations and boosts
-
--   `ROOT::Math::`**`LorentzRotation`**, 4D rotation (3D rotation plus a
-    boost) described by a 4x4 matrix
-
--   `ROOT::Math::`**`Boost`**, a Lorentz boost in an arbitrary direction
-    and described by a 4x4 symmetrix matrix (10 numbers)
-
--   `ROOT::Math::`**`BoostX`**, a boost in the X axis direction
-
--   `ROOT::Math::`**`BoostY`**, a boost in the Y axis direction
-
--   `ROOT::Math::`**`BoostZ`**, a boost in the Z axis direction
-
-#### Constructors
-
-All rotations and transformations are default constructible (giving the
-identity transformation). All rotations are constructible taking a
-number of scalar arguments matching the number (and order of
-components).
-
-``` {.cpp}
-   Rotation3D  rI;                 //a summy rotation (Identity matrix)
-   RotationX   rX(PI);             //a RotationX with an angle PI
-   EulerAngles rE(phi,theta,psi);  //an Euler rotation with phi,
-                                   //theta,psi angles
-   XYZVector   u(ux,uy,uz);
-   AxisAngle   rA(u,delta);        //a rotation based on direction u,
-                                   //angle delta
-```
-
-In addition, all rotations and transformations (other than the axial
-rotations) and transformations are constructible from (`begin`,`end`)
-iterators or from pointers behave like iterators.
-
-``` {.cpp}
-   double      data[9];
-   //create a rotation from a rotation matrix
-   Rotation3D  r(data,data+9);
-   std::vector w(12);
-   //create Transform3D from std::vector content
-   Transform3D t(w.begin(),w.end());
-```
-
-All rotations, except the axial rotations, are constructible and
-assigned from any other type of rotation (including the axial):
-
-``` {.cpp}
-   //create a rotation 3D from a rotation along X axis of angle PI
-   Rotation3D  r(ROOT::Math::RotationX(PI));
-
-   //construct an Euler rotation from A Rotation3D
-   EulerAngles r2(r);
-
-   //assign an Axis rotation from an Euler Rotation
-   AxisAngle   r3; r3 = r2;
-```
-
-**`Transform3D`** (rotation + translation) can be constructed from a
-rotation and a translation vector:
-
-``` {.cpp}
-   Rotation3D  r;
-   XYZVector   v;
-   Transform3D t1(r,v);   //construct from rotation and then
-                          //translation
-   Transform3D t2(v,r);   //construct inverse from first translation
-                          //then rotation
-   Transform3D t3(r);     //construct from only a rotation
-                          //(zero translation)
-   Transform3D t4(v);     //construct from only translation
-                          //(identity rotation)
-```
-
-#### Operations
-
-All transformations can be applied to vector and points using the
-operator \* or using the operator()
-
-``` {.cpp}
-   XYZVector  v1(...);
-   Rotation3D r(...);
-   XYZVector  v2 = r*v1;       //rotate vector v1 using r
-   v2 = r(v1);                 //equivalent
-```
-
-Transformations can be combined using the operator `*`. Rotation,
-translation and **`Transform3D`** classes can be all combined with the
-operator \*. The result of a combination of a rotation and a translation
-will be a **`Transform3D`** class. Note that the rotations are not
-commutative, the order is then important.
-
-``` {.cpp}
-   Rotation3D  r1(...);
-   Rotation3D  r2(...);
-   Rotation3D  r3 = r2*r1; //a combine rotation r3 by
-                           //applying first r1 then r2
-```
-
-We can combine rotations of different types, like `Rotation3D` with any
-other type of rotations. The product of two different axial rotations
-returns a `Rotation3D`:
-
-``` {.cpp}
-   RotationX   rx(1.);
-   RotationY   ry(2.);
-   Rotation3D  r = ry * rx;       //rotation along X and then Y axis
-```
-
-It is also possible to invert all the transformation or return their
-inverse:
-
-``` {.cpp}
-   Rotation3D  r1(...);
-   r1.Invert(); //invert the rotation modifying its content
-   Rotation3D  r2 =r1.Inverse(); //return the inverse in a new
-                                 //rotation class
-```
-
-We have used rotation as examples, but all these operations can be
-applied to all the transformation classes.
-
-#### Set/GetComponents Methods
-
-Common methods to all transformations are `Get` and `SetComponents`.
-They can be used to retrieve all the scalar values on which the
-transformation is based.
-
-``` {.cpp}
-   RotationX  rx;
-   rx.SetComponents(1.);      //set agle of the X rotation
-   double d[9] = {........};
-   Rotation3D r;
-   r.SetComponents(d,d+9);    //set 9 components of 3D rotation
-   double d[16];
-   LorentzRotation lr;
-   lr.GetComponents(d,d+16);  //get 16 components of a LorentzRotation
-   TMatrixD(3,4) m;
-   Transform3D t;
-   t.GetComponens(m);         //fill 3x4 matrix with components of t
-```
-
-The` GetComponents` and `SetComponents` methods can be used with a
-signature based iterators or by using any foreign matrix which
-implements the `operator(i,j)` or a different signatures depending on
-the transformation type. For more details on all methods see the
-reference documentation of any specific transformation class.
-
-### Example with External Packages
-
-
-#### Connection to Linear Algebra Classes
-
-It is possible to use the vector and rotation classes together with the
-linear algebra classes and to set and get the contents of any 3D or 4D
-vector from a linear algebra vector class which implements an iterator
-or something which behaves like an iterator. For example a pointer to a
-C array (double`*`) behaves like an iterator. It is then assumed that
-the coordinates, like (`x,y,z`) will be stored contiguously.
-
-``` {.cpp}
-   TVectorD   r2(N); //ROOT Linear Algebra Vector containing
-                     //many vectors
-   XYZVector  v2;
-   //construct vector from x=r[INDEX], y=r[INDEX+1], z=r[INDEX+2]
-   v2.SetCoordinates(&r2[INDEX],&r2[index]+3);
-```
-
-To fill a linear algebra vector from a 3D or 4D vector, with
-`GetCoordinates()` one can get the internal coordinate data.
-
-``` {.cpp}
-   HepVector      c(3);        //CLHEP Linear algebra vector
-   //fill HepVector c with c[0]=x, c[1]=y, c[2]=z
-   v2.GetCoordinates(&c[0],&c[index]+3)
-```
-
-or using **`TVectorD`**:
-
-``` {.cpp}
-   double   *data[3];
-   v2.GetCoordinates(data,data+3);
-   TVectorD  r1(3,data); //create a new Linear Algebra vector
-                         //copying the data
-```
-
-In the case of transformations, constructor and method to set`/`get
-components exist with linear algebra matrices. The requisite is that the
-matrix data are stored, for example in the case of a Lorentz rotation,
-from (`0,0`) thru (`3,3`)
-
-``` {.cpp}
-   TMatrixD(4,4)   m;
-   LorentzRotation r(m);       //create Lorentz r
-```
-
-#### Connection to Other Vector Classes
-
-The 3D and 4D vectors of the `GenVector` package can be constructed and
-assigned from any vector which satisfies the following requisites:
-
--   for 3D vectors implementing the `x()`, `y()` and `z()` methods
-
--   for Lorentz vectors implementing the `x()`, `y()`, `z()` and `t()`
-    methods.
-
-``` {.cpp}
-   CLHEP::Hep3Vector hv;
-   XYZVector         v1(hv);      //create  3D vector from
-                                  //CLHEP 3D Vector
-   HepGeom::Point3D  hp;
-   XYZPoint          p1(hp);      //create a 3D p
-```
-
-
-
-
-
-## Linear Algebra: SMatrix Package
-
-
-The ROOT Linear algebra package is documented in a separate chapter (see
-"Linear Algebra in ROOT"). `SMatrix` is a C++ package, for high
-performance vector and matrix computations. It has been introduced in
-ROOT v5.08. It is optimized for describing small matrices and vectors
-and It can be used only in problems when the size of the matrices is
-known at compile time, like in the tracking reconstruction of physics
-experiments. It is based on a C++ technique, called expression
-templates, to achieve an high level optimization. The C++ templates can
-be used to implement vector and matrix expressions such that these
-expressions can be transformed at compile time to code which is
-equivalent to hand optimized code in a low-level language like FORTRAN
-or C (see for example T. Veldhuizen, Expression Templates, C++ Report,
-1995).
-
-The `SMatrix` has been developed initially by T. Glebe in
-Max-Planck-Institut, Heidelberg, as part of the `HeraB` analysis
-framework. A subset of the original package has been now incorporated in
-the ROOT distribution, with the aim to provide a stand-alone and high
-performance matrix package. The API of the current package differs from
-the original one, in order to be compliant to the ROOT coding
-conventions.
-
-`SMatrix` contains the generic **`ROOT::Math::SMatrix`** and
-**`ROOT::Math::SVector`** classes for describing matrices and vectors of
-arbitrary dimensions and of arbitrary type. The classes are templated on
-the scalar type and on the size, like number of rows and columns for a
-matrix . Therefore, the matrix/vector dimension has to be known at
-compile time. An advantage of using the dimension as template parameters
-is that the correctness of dimension in the matrix/vector operations can
-be checked at compile time.
-
-`SMatrix` supports, since ROOT v5.10, symmetric matrices using a storage
-class (**`ROOT::Math::MatRepSym`**) which contains only the `N*(N+1)/2`
-independent element of a `NxN` symmetric matrix. It is not in the
-mandate of this package to provide complete linear algebra
-functionality. It provides basic matrix and vector functions such as
-matrix-matrix, matrix-vector, vector-vector operations, plus some extra
-functionality for square matrices, like inversion and determinant
-calculation. The inversion is based on the optimized Cramer method for
-squared matrices of size up to `6x6`.
-
-The `SMatrix` package contains only header files. Normally one does not
-need to build any library. In the ROOT distribution a library,
-`libSmatrix` is produced with the C++ dictionary information for squared
-and symmetric matrices and vectors up to dimension 7 and based on
-**`Double_t`**, **`Float_t`** and **`Double32_t`**. The following
-paragraphs describe the main characteristics of the matrix and vector
-classes. More detailed information about the `SMatrix` classes API is
-available in the
-[online reference documentation](online reference documentation).
-
-### Example: Vector Class (SVector)
-
-
-The template class **`ROOT::Math::SVector`** represents `n`-dimensional
-vectors for objects of arbitrary type. This class has 2 template
-parameters, which define at compile time, its properties: 1) type of the
-contained elements (for example *float* or *double*); 2) size of the
-vector. The use of this dictionary is mandatory if one want to use
-`Smatrix` in Cling and with I/O.
-
-#### Creating a Vector
-
-The following constructors are available to create a vector:
-
--   Default constructor for a zero vector (all elements equal to zero).
-
--   Constructor (and assignment) from a vector expression, like
-    `v=p*q+w`. Due to the expression template technique, no temporary
-    objects are created in this operation.
-
--   Constructor by passing directly the elements. This is possible only
-    for vectors up to size 10.
-
--   Constructor from an iterator copying the data referred by the
-    iterator. It is possible to specify the *begin* and *end* of the
-    iterator or the *begin* and the *size*. Note that for the Vector the
-    iterator is not generic and must be of type `T*`, where `T` is the
-    type of the contained elements.
-
-In the following example we assume that we are using the namespace
-**`ROOT::Math`**
-
-``` {.cpp}
-   //create an empty vector of size 3 ( v[0]=v[1]=v[2]=0)
-   SVector<double,3> v;
-   double d[3] = {1,2,3};
-   SVector<double,3> v(d,3);  //create a vector from a C array
-```
-
-#### Accessing and Setting Methods
-
-The single vector elements can be set or retrieved using the
-`operator[i]`, `operator(i)` or the iterator interface. Notice that the
-index starts from zero and not from one as in FORTRAN. Also no check is
-performed on the passed index. The full vector elements can be set also
-by using the SetElements function passing a generic iterator.
-
-``` {.cpp}
-   double x = m(i);          // return the i-th element
-   x = *(m.begin()+i);       // return the i-th element
-   v[0] = 1;                 // set the first element
-   v(1) = 2;                 // set the second element
-   *(v.begin()+3) = 3;       // set the third element
-   std::vector<double> w(3);
-
-   // set vector elements from a std::vector<double>::iterator
-   v.SetElements(w.begin(),w.end());
-```
-
-In addition there are methods to place a sub-vector in a vector. If the
-size of the sub-vector is larger than the vector size a static assert (a
-compilation error) is produced.
-
-``` {.cpp}
-   SVector>double,N>  v;
-   SVector>double,M>  w;
-   // M <= N otherwise a compilation error is obtained later
-   // place a vector of size M starting from
-   // element ioff, v[ioff+i]=w[i]
-   v.Place_at(w,ioff);
-   // return a sub-vector of size M starting from
-   // v[ioff]: w[i]=v[ioff+i]
-   w = v.Sub < SVector>double,M> > (ioff);
-```
-
-For the vector functions see later in the Matrix and Vector Operators
-and Functions paragraph.
-
-### Example: Matrix Class (SMatrix)
-
-
-The template class **`ROOT::Math::SMatrix`** represents a matrix of
-arbitrary type with `nrows` `x` `ncol` dimension. The class has 4
-template parameters, which define at compile time, its properties:
-
--   type of the contained elements, T, for example float or double;
-
--   number of rows;
-
--   number of columns;
-
--   representation type. This is a class describing the underlined
-    storage model of the Matrix. Presently exists only two types of this
-    class:
-
--   **`ROOT::Math::MatRepStd`** for a general `nrows x ncols` matrix.
-    This class is itself a template on the contained type `T`, the
-    number of rows and the number of columns. Its data member is an
-    array `T[nrows*ncols]` containing the matrix data. The data are
-    stored in the row-major C convention. For example, for a matrix `M`,
-    of size `3x3`, the data `{a0,a1,...,a8}` are stored in the following
-    order:
-
-$$
-M =
-         \left(\begin{array}{ccc}
-         a_0 &  a_1  & a_2 \\
-         a_3 &  a_4  & a_5 \\
-         a_6 &  a_7  & a_8
-         \end{array}\right)
-$$
-
--   **`ROOT::Math::MatRepSym`** for a symmetric matrix of size `NxN`.
-    This class is a template on the contained type and on the symmetric
-    matrix size `N`. It has as data member an array of type `T` of size
-    `N*(N+1)/2`, containing the lower diagonal block of the matrix. The
-    order follows the lower diagonal block, still in a row-major
-    convention. For example for a symmetric `3x3` matrix the order of
-    the `6` independent elements `{a0,a1,...,a5}` is:
-
-$$
-M =
-         \left(\begin{array}{ccc}
-         a_0 &  a_1  & a_3 \\
-         a_1 &  a_2  & a_4 \\
-         a_3 &  a_4  & a_5
-         \end{array}\right)
-$$
-
-#### Creating a Matrix
-
-The following constructors are available to create a matrix:
-
--   Default constructor for a zero matrix (all elements equal to zero).
-
--   Constructor of an identity matrix.
-
--   Copy constructor (and assignment) for a matrix with the same
-    representation, or from a different one when possible, for example
-    from a symmetric to a general matrix.
-
--   Constructor (and assignment) from a matrix expression, like
-    `D=A*B+C`. Due to the expression template technique, no temporary
-    objects are created in this operation. In the case of an operation
-    like `A=A*B+C`, a temporary object is needed and it is created
-    automatically to store the intermediary result in order to preserve
-    the validity of this operation.
-
--   Constructor from a generic STL-like iterator copying the data
-    referred by the iterator, following its order. It is both possible
-    to specify the begin and end of the iterator or the begin and the
-    size. In case of a symmetric matrix, it is required only the
-    triangular block and the user can specify whether giving a block
-    representing the lower (default case) or the upper diagonal part.
-
-Here are some examples on how to create a matrix. We use typedef's in
-the following examples to avoid the full C++ names for the matrix
-classes. Notice that for a general matrix the representation has the
-default value, **`ROOT::Math::MatRepStd`**, and it is not needed to be
-specified. Furthermore, for a general square matrix, the number of
-column may be as well omitted.
-
-``` {.cpp}
-   // typedef definitions used in the following declarations
-   typedef ROOT::Math::SMatrix<double,3>       SMatrix33;
-   typedef ROOT::Math::SMatrix<double,2>       SMatrix22;
-   typedef ROOT::Math::SMatrix<double,3,3,
-   ROOT::Math::MatRepSym<double,3>> SMatrixSym3;
-   typedef ROOT::Math::SVector>double,2>       SVector2;
-   typedef ROOT::Math::SVector>double,3>       SVector3;
-   typedef ROOT::Math::SVector>double,6>       SVector6;
-   SMatrix33   m0;                         // create a zero 3x3 matrix
-   // create an 3x3 identity matrix
-   SMatrix33   i = ROOT::Math::SMatrixIdentity();
-   double   a[9] = {1,2,3,4,5,6,7,8,9};    // input matrix data
-   // create a matrix using the a[] data
-   SMatrix33   m(a,9);             // this will produce the 3x3 matrix
-                                   //    (  1    2    3  )
-                                   //    (  4    5    6  )
-                                   //    (  7    8    9  )
-```
-
-Example to fill a symmetric matrix from an `std::vector`:
-
-``` {.cpp}
-   std::vector<double> v(6);
-   for (int i = 0; i<6; ++i) v[i] = double(i+1);
-   SMatrixSym3  s(v.begin(),v.end())   // this will produce the
-                                       // symmetric  matrix
-                                       //    (  1    2    4  )
-                                       //    (  2    3    5  )
-                                       //    (  4    5    6  )
-   //create a general matrix from a symmetric matrix (the opposite
-   // will not compile)
-   SMatrix33    m2 = s;
-```
-
-#### Accessing and Setting Methods
-
-The matrix elements can be set using the `operator()(irow,icol)`, where
-`irow` and `icol` are the row and column indexes or by using the
-iterator interface. Notice that the indexes start from zero and not from
-one as in FORTRAN. Furthermore, all the matrix elements can be set also
-by using the SetElements function passing a generic iterator. The
-elements can be accessed by the same methods as well as by using the
-function `ROOT::Math::SMatrix::apply`. The `apply(i)` has exactly the
-same behavior for general and symmetric matrices; in contrast to the
-iterator access methods which behave differently (it follows the data
-order).
-
-``` {.cpp}
-   SMatrix33   m;
-   m(0,0) = 1;        // set the element in first row and first column
-   *(m.begin()+1) = 2;      // set the second element (0,1)
-   double d[9]={1,2,3,4,5,6,7,8,9};
-   m.SetElements(d,d+9);    // set the d[] values in m
-   double x = m(2,1);       // return the element in 3
-   x = m.apply(7);          // return the 8-th element (row=2,col=1)
-   x = *(m.begin()+7);      // return the 8-th element (row=2,col=1)
-   // symmetric matrices
-   //(note the difference in behavior between apply and the iterators)
-   x = *(m.begin()+4)       // return the element (row=2,col=1)
-   x = m.apply(7);          // returns again the (row=2,col=1) element
-```
-
-There are methods to place and/or retrieve **`ROOT::Math::SVector`**
-objects as rows or columns in (from) a matrix. In addition one can put
-(get) a sub-matrix as another **`ROOT::Math::SMatrix`** object in a
-matrix. If the size of the sub-vector or sub-matrix is larger than the
-matrix size a static assert (a compilation error) is produced. The
-non-const methods are:
-
-``` {.cpp}
-   SMatrix33 m;
-   SVector2  v2(1,2);
-   // place a vector in the first row from
-   // element (0,1) : m(0,1)=v2[0]
-   m.Place_in_row(v2,0,1);
-   // place the vector in the second column from
-   // (0,1) : m(0,1) = v2[0]
-   m.Place in_col(v2,0,1);
-   SMatrix22 m2;
-   // place m2 in m starting from the
-   // element (1,1) : m(1,1) = m2(0,0)
-   m.Place_at(m2,1,1);
-   SVector3 v3(1,2,3);
-   // set v3 as the diagonal elements
-   // of m  : m(i,i) = v3[i] for i=0,1,2
-   m.SetDiagonal(v3)
-```
-
-The const methods retrieving contents (getting slices of a matrix) are:
-
-``` {.cpp}
-   a = {1,2,3,4,5,6,7,8,9};
-   SMatrix33       m(a,a+9);
-   SVector3 irow = m.Row(0);     // return as vector the first row
-   SVector3 jcol = m.Col(1);     // return as vector the second column
-
-   // return a slice of the first row from
-   // (0,1): r2[0]= m(0,1); r2[1]=m(0,2)
-   SVector2 r2   =  m.SubRow<SVector2> (0,1);
-   // return a slice of the second column from
-   // (0,1): c2[0] = m(0,1); c2[1] = m(1,1)
-   SVector2 c2   =  m.SubCol<SVector2> (1,0);
-
-   // return a sub-matrix 2x2 with the upper left corner at(1,1)
-   SMatrix22 subM = m.Sub<SMatrix22>   (1,1);
-
-   // return the diagonal element in a SVector
-   SVector3  diag = m.Diagonal();
-
-   // return the upper(lower) block of the matrix m
-   SVector6 vub = m.UpperBlock();       //  vub = [ 1, 2, 3, 5, 6, 9 ]
-   SVector6 vlb = m.LowerBlock();       //  vlb = [ 1, 4, 5, 7, 8, 9 ]
-```
-
-#### Linear Algebra Matrix Functions (Inversion, Determinant)
-
-Only limited linear algebra functionality is available for `SMatrix`. It
-is possible for squared matrices `NxN`, to find the inverse or to
-calculate the determinant. Different inversion algorithms are used if
-the matrix is smaller than `6x6` or if it is symmetric. In the case of a
-small matrix, a faster direct inversion is used. For a large
-`(N>6) `symmetric matrix the Bunch-Kaufman diagonal pivoting method is
-used while for a large `(N>6)` general matrix an LU factorization is
-performed using the same algorithm as in the CERNLIB routine `dinv`.
-
-``` {.cpp}
-   // Invert a NxN matrix.
-   // The inverted matrix replaces the existing one if the
-   // result is successful
-   bool ret = m.Invert();               // return the inverse matrix of m.
-
-   // If the inversion fails ifail is different than zero  ???
-   int ifail = 0;
-   ifail = m.Inverse(ifail);
-
-   // determinant of a square matrix - calculate the determinant
-   // modyfing the matrix content and returns it if the calculation
-   // was successful
-   double det;
-   bool ret = m.Det(det);
-
-   // calculate determinant by using a temporary matrix; preserves
-   // matrix content
-   bool ret = n.Det2(det);
-```
-
-### Example: Matrix and Vector Functions and Operators
-
-
-#### Matrix and Vector Operators
-
-The **`ROOT::Math::SVector`** and **`ROOT::Math::SMatrix`** classes
-define the following operators described below. The `m1`, `m2`, `m3` are
-vectors or matrices of the same type (and size) and `a` is a scalar
-value:
-
-``` {.cpp}
-   m1 == m2  // returns whether m1 is equal to m2
-             // (element by element comparison)
-   m1 != m2  // returns whether m1 is NOT equal to m2
-             // (element by element comparison)
-   m1 < m2   // returns whether m1 is less than m2
-             // (element wise comparison)
-   m1 > m2   // returns whether m1 is greater than m2
-             // (element wise comparison)
-
-   // in the following m1 and m3 can be general and m2 symmetric,
-   // but not vice-versa
-
-   m1 += m2           // add m2 to m1
-   m1 -= m2           // subtract m2 to m1
-   m3 = m1 + m2       // addition
-   m1 - m2            // subtraction
-
-   // Multiplication and division via a scalar value a
-
-   m3 = a*m1; m3 = m1*a; m3 = m1/a;
-```
-
-**Vector-Vector multiplication:** The operator `*` defines an element by
-element multiplication between vectors. For the standard vector-vector
-algebraic multiplication returning a scalar, `vTv` (dot product), one
-must use the **`ROOT::Math::Dot` function. In addition, the Cross (only
-for vector sizes of 3), `ROOT::Math::`**`Cross`, and the Tensor product,
-`ROOT::Math::TensorProd`, are defined.
-
-**Matrix - Vector multiplication:** The operator `*` defines the
-matrix-vector multiplication:
-$y_i = \sum_j M_{i,j} x_j$. The operation compiles only if the matrix
-and the vectors have the right sizes.
-
-``` {.cpp}
-   //M is a N1xN2 matrix, x is a N2 size vector, y is a N1 size vector
-   y = M * x
-```
-
-**Matrix - Matrix multiplication:** The operator `*` defines the
-matrix-matrix multiplication:
-$C_{i,j} = \sum_k A_{i,k} B_{k,j}$.
-
-``` {.cpp}
-   // A is a N1xN2 matrix, B is a N2xN3 matrix and C is a N1xN3 matrix
-   C = A * B
-```
-
-The operation compiles only if the matrices have the right size. In the
-case that `A` and `B` are symmetric matrices, `C` is a general one,
-since their product is not guaranteed to be symmetric.
-
-### Matrix and Vector Functions
-
-
-The most used matrix functions are:
-
--   `ROOT::Math::Transpose(M)` returns the transpose matrix `MT`
-
--   `ROOT::Math::Similarity(v,M)` returns the scalar value resulting
-    from the matrix-vector product `vTMv`
-
--   `ROOT::Math::Similarity(U,M)` returns the matrix resulting from the
-    product: `U M UT`. If `M` is symmetric, the returned resulting
-    matrix is also symmetric
-
--   `ROOT::Math::SimilarityT(U,M)` returns the matrix resulting from the
-    product: `UT M U`. If `M` is symmetric, the returned resulting
-    matrix is also symmetric
-
-The major vector functions are:
-
--   `ROOT::Math::Dot(v1,v2)` returns the scalar value resulting from the
-    vector dot product
-
--   `ROOT::Math::Cross(v1,v2)` returns the vector cross product for two
-    vectors of size 3. Note that the `Cross` product is not defined for
-    other vector sizes
-
--   `ROOT::Math::Unit(v)` returns unit vector. One can use also the
-    `v.Unit() `method.
-
--   `ROOT::Math::TensorProd(v1,v2)` returns a general matrix `M `of size
-    `N1xN2` resulting from the tensor product between the vector `v1` of
-    size `N1` and `v2` of size `N2`:
-
-For a list of all the available matrix and vector functions see the
-`SMatrix` online reference documentation.
-
-#### Matrix and Vector I/O
-
-One can print (or write in an output stream) Vectors and Matrices) using
-the `Print` method or the `<<` operator:
-
-``` {.cpp}
-   // m is a SMatrix or a SVector object
-   m.Print(std::cout);
-   std::cout << m << std::endl;
-```
-
-In the ROOT distribution, the Cling dictionary is generated for `SMatrix`
-and `SVector` for for **`Double_t`**, **`Float_t`** and **`Double32_t`**
-up to dimension 7. This allows the possibility to store them in a ROOT
-file.
-
-
-## ROOT Statistics Classes
-
-
-### Classes for Computing Limits and Confidence Levels
-
-
-**`TFeldmanCousins`** class calculates the `CL` upper/lower limit for a
-Poisson process using the Feldman-Cousins method (as described in PRD
-V57 \#7, p3873-3889). No treatment is provided in this method for the
-uncertainties in the signal or the background.
-
-**`TRolke`** computes confidence intervals for the rate of a Poisson
-process in the presence of background and efficiency, using the profile
-likelihood technique for treating the uncertainties in the efficiency
-and background estimate. The signal is always assumed to be Poisson;
-background may be Poisson, Gaussian, or user-supplied; efficiency may be
-Binomial, Gaussian, or user-supplied. See publication at Nucl. Instrum.
-Meth. A551:493-503,2005.
-
-**`TLimit`** class computes 95% C.L. limits using the Likelihood ratio
-semi-Bayesian method ( <CLs> method; see e.g. T. Junk, NIM A434, p.
-435-443, 1999). It takes signal background and data histograms wrapped
-in a `TLimitDataSource` as input, and runs a set of Monte Carlo
-experiments in order to compute the limits. If needed, inputs are
-fluctuated according to systematic.
-
-### Specialized Classes for Fitting
-
-
-**`TFractionFitter`** fits Monte Carlo (MC) fractions to data histogram
-(a la HMCMLL, R. Barlow and C. Beeston, Comp. Phys. Comm. 77 (1993)
-219-228). It takes into account both data and Monte Carlo statistical
-uncertainties through a likelihood fit using Poisson statistics.
-However, the template (MC) predictions are also varied within
-statistics, leading to additional contributions to the overall
-likelihood. This leads to many more fit parameters (one per bin per
-template), but the minimization with respect to these additional
-parameters is done analytically rather than introducing them as formal
-fit parameters. Some special care needs to be taken in the case of bins
-with zero content.
-
-**`TMultiDimFit`** implements multi-dimensional function
-parametrization for multi-dimensional data by fitting them to
-multi-dimensional data using polynomial or Chebyshev or Legendre
-polynomial
-
-**`TSpectrum`** contains advanced spectra processing functions for
-1- and 2-dimensional background estimation, smoothing, deconvolution,
-peak search and fitting, and orthogonal transformations.
-
-**`RooFit`** is a complete toolkit for fitting and data analysis
-modeling (see the RooFit User Guide at
-ftp://root.cern.ch/root/doc/RooFit\_Users\_Manual\_2.07-29.pdf)
-
-**`TSplot`** to disentangle signal from background via an extended
-maximum likelihood fit and with a tool to access the quality and
-validity of the fit producing distributions for the control variables.
-(see M. Pivk and F.R. Le Diberder, Nucl. Inst. Meth.A 555, 356-369,
-2005).
-
-### Multi-variate Analysis Classes
-
-
-**`TMultiLayerPerceptron`** is a Neural Network class (see for more
-details the chapter "Neural Networks").
-
-**`TPrincipal`** provides the Principal Component Analysis.
-
-**`TRobustEstimator`** is a robust method for minimum covariance
-determinant estimator (MCD).
-
-**`TMVA`** is a package for multivariate data analysis (see
-<https://github.com/root-project/root/blob/master/documentation/tmva/UsersGuide/TMVAUsersGuide.pdf> the User's Guide).
diff --git a/documentation/users-guide/Networking.md b/documentation/users-guide/Networking.md
deleted file mode 100644
index 434bca2c27277..0000000000000
--- a/documentation/users-guide/Networking.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# Networking
-
-
-In this chapter, you will learn how to send data over the network using
-the ROOT socket classes.
-
-## Setting-up a Connection
-
-
-*On the serverside*, we create a **`TServerSocket`** to wait for a
-connection request over the network. If the request is accepted, it
-returns a full-duplex socket. Once the connection is accepted, we can
-communicate to the client that we are ready to go by sending the string
-"go", and we can close the server socket.
-
-``` {.cpp}
-{ // server
-   TServerSocket *ss = new TServerSocket(9090,kTRUE);
-   TSocket *socket = ss->Accept();
-   socket->Send("go");
-   ss->Close();
-}
-```
-
-*On the clientside*, we create a socket and ask the socket to receive
-input.
-
-``` {.cpp}
-{ // client
-   TSocket *socket = new TSocket("localhost",9090);
-   Char str[32];
-   socket->Recv(str,32);
-}
-```
-
-## Sending Objects over the Network
-
-
-We have just established a connection and you just saw how to send and
-receive a string with the example "go". Now let's send a histogram.
-
-*To send an object (in our case on the client side*) it has to derive
-from **`TObject`** class because it uses the `Streamers` to fill a
-buffer that is then sent over the connection. On the receiving side, the
-`Streamers` are used to read the object from the message sent via the
-socket. For network communication, we have a specialized **`TBuffer`**,
-a descendant of **`TBuffer`** called **`TMessage`**. In the following
-example, we create a **`TMessage`** with the intention to store an
-object, hence the constant `kMESS_OBJECT` in the constructor. We create
-and fill the histogram and write it into the message. Then we call
-**`TSocket`**`::Send` to send the message with the histogram.
-
-``` {.cpp}
-...
-// create an object to be sent
-TH1F *hpx = new TH1F("hpx","px distribution",100,-4,4);
-hpx->FillRandom("gaus",1000);
-
-// create a TMessage to send the object
-TMessage message(kMESS_OBJECT);
-
-// write the histogram into the message buffer
-message.WriteObject(hpx);
-
-// send the message
-socket->Send(message);
-...
-```
-
-On the receiving end (in our case the server side), we write a while
-loop to wait and receive a message with a histogram. Once we have a
-message, we call `TMessage::ReadObject`, which returns a pointer to
-**`TObject`**. We have to cast it to a **`TH1`** pointer, and now we
-have a histogram. At the end of the loop, the message is deleted, and
-another one is created at the beginning.
-
-``` {.cpp}
-while (1) {
-   TMessage *message;
-   socket->Recv(message);
-   TH1 *h = (TH1*)message->ReadObject(message->GetClass());
-   delete message;
-}
-```
-
-## Closing the Connection
-
-
-Once we are done sending objects, we close the connection by closing the
-sockets at both ends.
-
-``` {.cpp}
-Socket->Close();
-```
-
-This diagram summarizes the steps we just covered:
-
-![Server - Client setting-up and closing the connection](pictures/080001FF.png)
-
-## A Server with Multiple Sockets
-
-
-Chances are that your server has to be able to receive data from
-multiple clients. The class we need for this is **`TMonitor`**. It lets
-you add sockets and the `TMonitor::Select` method returns the socket
-with data waiting. Sockets can be added, removed, or enabled and
-disabled. Here is an example of a server that has a **`TMonitor`** to
-manage multiple sockets:
-
-``` {.cpp}
-{
-   TServerSocket *ss = new TServerSocket (9090, kTRUE);
-
-   // Accept a connection and return a full-duplex communication socket.
-   TSocket *s0 = ss->Accept();
-   TSocket *s1 = ss->Accept();
-
-   // tell the clients to start
-   s0->Send("go 0");
-   s1->Send("go 1");
-
-   // Close the server socket (unless we will use it
-   // later to wait for another connection).
-   ss->Close();
-
-   TMonitor *mon = new TMonitor;
-   mon->Add(s0);
-   mon->Add(s1);
-
-   while (1) {
-      TMessage *mess;
-      TSocket  *s;
-      s = mon->Select();
-      s->Recv(mess);
-      ...
-   }
-}
-```
-
-The full code for the example above is in
-`$ROOTSYS/tutorials/net/hserv.C and`
-
-`$ROOTSYS/tutorials/net/hclient.C`.
diff --git a/documentation/users-guide/ObjectOwnership.md b/documentation/users-guide/ObjectOwnership.md
deleted file mode 100644
index c204ef8b5c8ab..0000000000000
--- a/documentation/users-guide/ObjectOwnership.md
+++ /dev/null
@@ -1,259 +0,0 @@
-# Object Ownership
-
-
-An object has ownership of another object if it has permission to
-delete it. Usually a collection or a parent object such as a pad holds
-ownership. To prevent memory leaks and multiple attempts to delete an
-object, you need to know which objects ROOT owns and which are owned
-by you.
-
-The following rules apply to the ROOT classes.
-
--   Histograms, trees, and event lists created by the user are owned
-    by current directory (***`gDirectory`***). When the current
-    directory is closed or deleted the objects it owns are deleted.
-
--   The `TROOT` master object (***`gROOT`***) has several collections
-    of objects. Objects that are members of these collections are
-    owned by ***`gROOT`*** see "Ownership by the Master TROOT Object
-    (gROOT).
-
--   Objects created by another object, for example the function object
-    (e.g.**`TF1`**) created by the **`TH1::Fit `method is owned by the
-    histogram.**
-
--   An object created by `DrawCopy` methods, is owned by the pad it is
-    drawn in.
-
-If an object fits none of these cases, the user has ownership. The
-next paragraphs describe each rule and user ownership in more detail.
-
-## Ownership by Current Directory (gDirectory)
-
-
-When a histogram, tree, or event list (**`TEventList`**) is created,
-it is added to the list of objects in the current directory by
-default. You can get the list of objects in a directory and retrieve
-a pointer to a specific object with the `GetList` method. This example
-retrieves a histogram.
-
-``` {.cpp}
-   TH1F *h = (TH1F*)gDirectory->GetList()->FindObject("myHist");
-```
-
-The method `TDirectory::GetList()` returns a **`TList`** of objects in
-the directory. It looks in memory, and is implemented in all ROOT
-collections. You can change the directory of a histogram, tree, or
-event list with the `SetDirectory` method. Here we use a histogram for
-an example, but the same applies to trees and event lists.
-
-``` {.cpp}
-   h->SetDirectory(newDir);
-```
-
-You can also remove a histogram from a directory by using
-`SetDirectory(0)`. Once a histogram is removed from the directory, it
-will not be deleted when the directory is closed. It is now your
-responsibility to delete this histogram once you have finished with
-it. To change the default that automatically adds the histogram to the
-current directory, you can call the static function:
-
-``` {.cpp}
-   TH1::AddDirectory(kFALSE);
-```
-
-Not all histograms created here after will be added to the current
-directory. In this case, you own all histogram objects and you will
-need to delete them and clean up the references. You can still set the
-directory of a histogram by calling `SetDirectory` once it has been
-created as described above.
-
-Note that, when a file goes out of scope or is closed all objects on
-its object list are deleted.
-
-## Ownership by the Master TROOT Object (gROOT)
-
-
-The master object ***`gROOT`***`,` maintains several collections of
-objects. For example, a canvas is added to the collection of canvases
-and it is owned by the canvas collection.
-
-``` {.cpp}
-TSeqCollection* fFiles        List of TFile
-TSeqCollection* fMappedFiles  List of TMappedFile
-TSeqCollection* fSockets      List of TSocket and TServerSocket
-TSeqCollection* fCanvases     List of TCanvas
-TSeqCollection* fStyles       List of TStyle
-TSeqCollection* fFunctions    List of TF1, TF2, TF3
-TSeqCollection* fTasks        List of TTask
-TSeqCollection* fColors       List of TColor
-TSeqCollection* fGeometries   List of geometries
-TSeqCollection* fBrowsers     List of TBrowser
-TSeqCollection* fSpecials     List of special objects
-TSeqCollection* fCleanups     List of recursiveRemove collections
-```
-
-These collections are also displayed in the root folder of the
-`Object Browser`. Most of these collections are self explanatory. The
-special cases are the collections of specials and cleanups.
-
-### The Collection of Specials
-
-
-This collection contains objects of the following classes:
-**`TCutG`**, **`TMultiDimFit`**, **`TPrincipal`**, **`TChains`**. In
-addition it contains the ***`gHtml`*** object, ***`gMinuit`***
-objects, and the array of contours graphs (**`TGraph`**) created when
-calling the `Draw` method of a histogram with the `"CONT`, `LIST"`
-option.
-
-### Access to the Collection Contents
-
-
-The current content for a collection listed above can be accessed with
-the corresponding `gROOT->GetListOf` method (for example
-`gROOT->GetListOfCanvases`). In addition, `gROOT->GetListOfBrowsables`
-returns a collection of all objects visible on the left side panel in
-the browser. See the image of the Object Browser in the next figure.
-
-![The ROOT Object Browser](pictures/03000094.png)
-
-## Ownership by Other Objects
-
-
-When an object creates another, the creating object is the owner of the
-created one. For example:
-
-``` {.cpp}
-myHisto->Fit("gaus")
-```
-
-The call to Fit copies the global **`TF1`** Gaussian function and
-attaches the copy to the histogram. When the histogram is deleted, the
-copy is deleted also.
-
-When a pad is deleted or cleared, all objects in the pad with the
-`kCanDelete` bit set are deleted automatically. Currently the objects
-created by the `DrawCopy` methods, have the `kCanDelete` bit set and
-are therefore owned by the pad.
-
-## Ownership by the User
-
-
-The user owns all objects not described in one of the above cases.
-**`TObject`** has two bits, `kCanDelete` and `kMustCleanup`, that
-influence how an object is managed (in `TObject::fBits)`. These are in
-an enumeration in `TObject.h.` To set these bits do:
-
-``` {.cpp}
-MyObject->SetBit(kCanDelete)
-MyObject->SetBit(kMustCleanup)
-```
-
-The bits can be reset and tested with the `TObject::ResetBit` and
-**`TObject::TestBit` methods.**
-
-### The kCanDelete Bit
-
-
-The ***`gROOT`*** collections (see above) own their members and will
-delete them regardless of the `kCanDelete` bit. In all other
-collections, when the collection `Clear` method is called (i.e.
-**`TList::Clear())`**, members with the `kCanDelete` bit set, are
-deleted and removed from the collection. If the `kCanDelete` bit is
-not set, the object is only removed from the collection but not
-deleted.
-
-If a collection `Delete` (`TList::Delete()`) method is called, all
-objects in the collection are deleted without considering the
-`kCanDelete` bit. It is important to realize that deleting the
-collection (i.e. delete `MyCollection`), DOES NOT delete the members
-of the collection.
-
-If the user specified `MyCollection->SetOwner()` the collection owns
-the objects and delete `MyCollection` will delete all its members.
-Otherwise, you need to:
-
-``` {.cpp}
-   // delete all member objects in the collection
-   MyCollection->Delete();
-
-   // and delete the collection object
-   delete MyCollection;
-```
-
-Note that `kCanDelete` is automatically set by the `DrawCopy` method
-and the user can set it for any object. For example, the user must
-manage all graphics primitives. If you want **`TCanvas`** to delete
-the primitive you created you have to set the `kCanDelete` bit.
-
-The `kCanDelete` bit setting is displayed with `TObject::ls()`. The
-last number is either 1 or 0 and is the `kCanDelete` bit.
-
-``` {.cpp}
-root[] TCanvas MyCanvas("MyCanvas")
-root[] MyCanvas.Divide(2,1)
-root[] MyCanvas->cd(MyCanvas_1)
-root[] hstat.Draw()             // hstat is an existing TH1F
-root[] MyCanvas->cd(MyCanvas_2)
-root[] hstat.DrawCopy()         // DrawCopy sets the kCanDelete bit
-(class TH1*)0x88e73f8
-root[] MyCanvas.ls()
-Canvas Name=MyCanvas ...
- TCanvas ... Name= MyCanvas ...
-  TPad   ... Name= MyCanvas_1 ...
-   TFrame  ...
-   OBJ: TH1F    hstat   Event Histogram : 0
-   TPaveText   ... title
-   TPaveStats  ... stats
-  TPad ... Name= MyCanvas_2 ...
-   TFrame  ...
-   OBJ: TH1F    hstat   Event Histogram : 1
-   TPaveText   ... title
-TPaveStats  ... stats
-```
-
-### The kMustCleanup Bit
-
-
-When the `kMustCleanup` bit is set, the object destructor will remove
-the object and its references from all collections in the clean up
-collection (***`gROOT`***`::fCleanups`). An object can be in several
-collections, for example if an object is in a browser and on two
-canvases. If the `kMustCleanup` bit is set, it will be removed
-automatically from the browser and both canvases when the destructor
-of the object is called.
-
-The `kMustCleanup` bit is set:
-
--   When an object is added to a pad (or canvas) in
-    `TObject::AppendPad`.
-
--   When an object is added to a **`TBrowser`** with
-    **`TBrowser`**`::Add`.
-
--   When an object is added to a `TFolder with `**`TFolder`**`::Add`.
-
--   When creating an inspector canvas with `TInspectCanvas::Inspector`.
-
--   When creating a **`TCanvas`**.
-
--   When painting a frame for a pad, the frame's `kMustCleanup` is set
-    in `TPad::PaintPadFrame`
-
-The user can add their own collection to the collection of clean ups, to
-take advantage of the automatic garbage collection. For example:
-
-``` {.cpp}
-   // create two list
-   TList *myList1, *myList2;
-
-   // add both to of clean ups
-   gROOT->GetListOfCleanUps()->Add(myList1);
-   gROOT->GetListOfCleanUps()->Add(myList2);
-
-   // assuming myObject is in myList1 and myList2, when calling:
-   delete myObject;
-
-   // the object is deleted from both lists
-```
diff --git a/documentation/users-guide/PhysicsVectors.md b/documentation/users-guide/PhysicsVectors.md
deleted file mode 100644
index 0d5187346a1ed..0000000000000
--- a/documentation/users-guide/PhysicsVectors.md
+++ /dev/null
@@ -1,810 +0,0 @@
-# Physics Vectors
-
-
-The physics vector classes describe vectors in three and four dimensions
-and their rotation algorithms. The classes were ported to root from
-CLHEP see:
-
-<http://www.cern.ch/clhep/manual/UserGuide/Vector/vector.html>
-
-## The Physics Vector Classes
-
-
-In order to use the physics vector classes you will have to load the
-Physics library:
-
-``` {.cpp}
-gSystem.Load("libPhysics.so");
-```
-
-There are four classes in this package. They are:
-
-**`TVector3`** is a general three-vector. A **`TVector3`** may be
-expressed in Cartesian, polar, or cylindrical coordinates. Methods
-include dot and cross products, unit vectors and magnitudes, angles
-between vectors, and rotations and boosts. There are also functions of
-particular use to HEP, like pseudo-rapidity, projections, and transverse
-part of a **`TVector3`**, and kinetic methods on 4-vectors such as
-Invariant Mass of pairs or containers of particles`.`
-
-**`TLorentzVector`** is a general four-vector class, which can be used
-either for the description of position and time (`x`, `y`, `z`, `t`) or
-momentum and energy (`px`, `py`, `pz`, `E`). **`TRotation`** is a class
-describing a rotation of a **`TVector3`** object. **`TLorentzRotation`**
-is a class to describe the Lorentz transformations including Lorentz
-boosts and rotations. In addition, a **`TVector2`** is a basic
-implementation of a vector in two dimensions and is not part of the
-CLHEP translation.
-
-## TVector3
-
-
-![](pictures/030001A9.png)
-
-**`TVector3`** is a general three-vector
-class, which can be used for description of different vectors in 3D.
-Components of three vectors:
-
-- $x$, $y$, $z$ = basic components
-
-- $\theta$ = azimuth angle
-
-- $\phi$ = polar angle
-
-- magnitude = $mag$ = $\sqrt{x^2 + y^2 + z^2}$
-
-- transverse component = $perp$ = $\sqrt{x^2 + y^2}$
-
-Using the **`TVector3`** class, you should remember that it contains
-only common features of three vectors and lacks methods specific for
-some particular vector values. For example, it has no translated
-function because translation has no meaning for vectors.
-
-### Declaration / Access to the Components
-
-
-**`TVector3`** has been implemented as a vector of three `Double_t`
-variables, representing the Cartesian coordinates. By default the values
-are initialized to zero, however you can change them in the constructor:
-
-``` {.cpp}
-TVector3 v1;        // v1 = (0,0,0)
-TVector3 v2(1);     // v2 = (1,0,0)
-TVector3 v3(1,2,3); // v3 = (1,2,3)
-TVector3 v4(v2);    // v4 = v2
-```
-
-It is also possible (but not recommended) to initialize a **`TVector3`**
-with a `Double_t` or `Float_t C` array. You can get the components by
-name or by index:
-
-``` {.cpp}
-xx = v1.X();    or    xx = v1(0);
-yy = v1.Y();          yy = v1(1);
-zz = v1.Z();          zz = v1(2);
-```
-
-The methods `SetX()`, `SetY()`, `SetZ()` and `SetXYZ()` allow you to set
-the components:
-
-``` {.cpp}
-v1.SetX(1.); v1.SetY(2.); v1.SetZ(3.);
-v1.SetXYZ(1.,2.,3.);
-```
-
-### Other Coordinates
-
-
-To get information on the **`TVector3`** in spherical (`rho`, `phi`,
-`theta`) or cylindrical (`z`, `r`, `theta`) coordinates, the following
-methods can be used.
-
-``` {.cpp}
-Double_t m  = v.Mag();
-// get magnitude (=rho=Sqrt(x*x+y*y+z*z)))
-Double_t m2 = v.Mag2();    // get magnitude squared
-Double_t t  = v.Theta();   // get polar angle
-Double_t ct = v.CosTheta();// get cos of theta
-Double_t p  = v.Phi();     // get azimuth angle
-Double_t pp = v.Perp();    // get transverse component
-Double_t pp2= v.Perp2();   // get transverse squared
-```
-
-It is also possible to get the transverse component with respect to
-another vector:
-
-``` {.cpp}
-Double_t ppv1  = v.Perp(v1);
-Double_t pp2v1 = v.Perp2(v1);
-```
-
-The pseudo-rapidity `(eta = -ln (tan (theta/2)))` can be obtained by
-`Eta()` or `PseudoRapidity()`:
-
-``` {.cpp}
-Double_t eta = v.PseudoRapidity();
-```
-
-These setters change one of the non-Cartesian coordinates:
-
-``` {.cpp}
-v.SetTheta(.5);  // keeping rho and phi
-v.SetPhi(.8);    // keeping rho and theta
-v.SetMag(10.);   // keeping theta and phi
-v.SetPerp(3.);   // keeping z and phi
-```
-
-### Arithmetic / Comparison
-
-
-The **`TVector3`** class has operators to add, subtract, scale and
-compare vectors:
-
-``` {.cpp}
-v3  = -v1;
-v1  = v2+v3;
-v1 += v3;
-v1  = v1 - v3;
-v1 -= v3;
-v1 *= 10;
-v1  = 5*v2;
-if(v1 == v2) {...}
-if(v1 != v2) {...}
-```
-
-### Related Vectors
-
-
-``` {.cpp}
-v2 = v1.Unit();        // get unit vector parallel to v1
-v2 = v1.Orthogonal();  // get vector orthogonal to v1
-```
-
-### Scalar and Vector Products
-
-
-``` {.cpp}
-s = v1.Dot(v2);   // scalar product
-s = v1 * v2;      // scalar product
-v = v1.Cross(v2); // vector product
-```
-
-### Angle between Two Vectors
-
-
-``` {.cpp}
-Double_t a = v1.Angle(v2);
-```
-
-### Rotation around Axes
-
-
-``` {.cpp}
-v.RotateX(.5);
-v.RotateY(TMath::Pi());
-v.RotateZ(angle);
-```
-
-### Rotation around a Vector
-
-
-``` {.cpp}
-v1.Rotate(TMath::Pi()/4, v2); // rotation around v2
-```
-
-### Rotation by TRotation Class
-
-
-**`TVector3`** objects can be rotated by **`TRotation`** objects using
-the `Transform()` method, the operator `*=`, or the operator `*` of
-the **`TRotation`** class. See the later section on `TRotation.`
-
-``` {.cpp}
-TRotation m;
-...
-v1.Transform(m);
-v1 = m*v1;
-v1 *= m;                          // v1 = m*v1
-```
-
-### Transformation from Rotated Frame
-
-
-This code transforms v1 from the rotated frame (z' parallel to
-direction, x' in the theta plane and y' in the `xy` plane as well as
-perpendicular to the theta plane) to the (x, y, z) frame.
-
-``` {.cpp}
-TVector3 direction = v.Unit()
-v1.RotateUz(direction);      // direction must be TVector3 of unit length
-```
-
-## TRotation
-
-
-The **`TRotation`** class describes a rotation of **`TVector3`** object.
-It is a 3 \* 3 matrix of `Double_t`:
-
-$$\left|
-\begin{array}{ccc}
-         xx &  xy  & xz \\
-         yx &  yy  & yz \\
-         zx &  zy  & zz
-         \end{array}
-\right|$$
-
-It describes a so-called active rotation, i.e. a rotation of objects
-inside a static system of coordinates. In case you want to rotate the
-frame and want to know the coordinates of objects in the rotated system,
-you should apply the inverse rotation to the objects. If you want to
-transform coordinates from the rotated frame to the original frame you
-have to apply the direct transformation. A rotation around a specified
-axis means counterclockwise rotation around the positive direction of
-the axis.
-
-### Declaration, Access, Comparisons
-
-
-``` {.cpp}
-   TRotation r;        // r initialized as identity
-   TRotation m(r);     // m = r
-```
-
-There is no direct way to set the matrix elements - to ensure that a
-**`TRotation`** always describes a real rotation. But you can get the
-values by with the methods `XX()..ZZ()` or the `(,)` operator:
-
-``` {.cpp}
-   Double_t xx = r.XX();           // the same as xx=r(0,0)
-   xx = r(0,0);
-   if (r==m) {...}                 // test for equality
-   if (r!=m) {..}                  // test for inequality
-   if (r.IsIdentity()) {...}       // test for identity
-```
-
-### Rotation around Axes
-
-
-The following matrices describe counter-clockwise rotations around the
-coordinate axes and are implemented in: `RotateX()`,` RotateY()` and
-`RotateZ()`:
-
-$$
-Rx(a) = \left|
-\begin{array}{ccc}
-         1 &  0       & 0 \\
-         0 &  cos(a)  & -sin(a) \\
-         0 &  sin(a)  & cos(a)
-         \end{array}
-\right|
-Ry(a) = \left|
-\begin{array}{ccc}
-         cos(a)  &  0  & sin(a) \\
-              0  &  1  & 0 \\
-         -sin(a) &  0  & cos(a)
-         \end{array}
-\right|
-Rz(a) = \left|
-\begin{array}{ccc}
-         cos(a)  &  -sin(a)  & 0 \\
-         sin(a)  &   cos(a)  & 0 \\
-              0  &  0        & 1
-         \end{array}
-\right|
-$$
-
-``` {.cpp}
-   r.RotateX(TMath::Pi()); // rotation around the x-axis
-```
-
-### Rotation around Arbitrary Axis
-
-
-The `Rotate()` method allows you to rotate around an arbitrary vector
-(not necessary a unit one) and returns the result.
-
-``` {.cpp}
-   r.Rotate(TMath::Pi()/3,TVector3(3,4,5));
-```
-
-It is possible to find a unit vector and an angle, which describe the
-same rotation as the current one:
-
-``` {.cpp}
-   Double_t angle;
-   TVector3 axis;
-   r.GetAngleAxis(angle,axis);
-```
-
-### Rotation of Local Axes
-
-
-The `RotateAxes()method` adds a rotation of local axes to the current
-rotation and returns the result:
-
-``` {.cpp}
-   TVector3 newX(0,1,0);
-   TVector3 newY(0,0,1);
-   TVector3 newZ(1,0,0);
-   a.RotateAxes(newX,newX,newZ);
-```
-
-Methods `ThetaX()`, `ThetaY()`, `ThetaZ()`, `PhiX()`, `PhiY()`, `PhiZ()`
-return azimuth and polar angles of the rotated axes:
-
-``` {.cpp}
-   Double_t tx,ty,tz,px,py,pz;
-   tx= a.ThetaX();
-...
-   pz= a.PhiZ();
-```
-
-### Inverse Rotation
-
-
-``` {.cpp}
-   TRotation a,b;
-...
-   b = a.Inverse();// b is inverse of a, a is unchanged
-   b = a.Invert();// invert a and set b = a
-```
-
-### Compound Rotations
-
-
-The `operator *` has been implemented in a way that follows the
-mathematical notation of a product of the two matrices which describe
-the two consecutive rotations. Therefore, the second rotation should be
-placed first:
-
-``` {.cpp}
-   r = r2 * r1;
-```
-
-### Rotation of TVector3
-
-
-The **`TRotation`** class provides an `operator *` which allows
-expressing a rotation of a **`TVector3`** analog to the mathematical
-notation:
-
-$$
-\left|
-\begin{array}{c}
-         x' \\
-         y' \\
-         z'
-         \end{array}
-\right|
-=
-\left|
-\begin{array}{ccc}
-         xx  &  xy  & xz \\
-         yx  &  yy  & yz \\
-         zx  &  zy  & zz
-         \end{array}
-\right|
-\times
-\left|
-\begin{array}{c}
-         x \\
-         y \\
-         z
-         \end{array}
-\right|
-$$
-
-
-``` {.cpp}
-   TRotation r;
-   TVector3 v(1,1,1);
-   v = r * v;
-```
-
-You can also use the `Transform()` method or the `operator *=` of the
-**`TVector3`** class:
-
-``` {.cpp}
-   TVector3 v;
-   TRotation r;
-   v.Transform(r);
-```
-
-## TLorentzVector
-
-
-**`TLorentzVector`** is a general four-vector class, which can be used
-either for the description of position and time (`x`, `y`, `z`, `t`) or
-momentum and energy (`px`, `py`, `pz`, `E`).
-
-### Declaration
-
-
-**`TLorentzVector`** has been implemented as a set a **`TVector3`** and
-a `Double_t` variable. By default, all components are initialized by
-zero.
-
-``` {.cpp}
-TLorentzVector v1;  // initialized by (0.,0.,0.,0.)
-TLorentzVector v2(1.,1.,1.,1.);
-TLorentzVector v3(v1);
-TLorentzVector v4(TVector3(1.,2.,3.),4.);
-```
-
-For backward compatibility there are two constructors from a `Double_t`
-and `Float_t` array.
-
-### Access to Components
-
-
-There are two sets of access functions to the components of a
-**`TLorentzVector`**: `X()`, `Y()`, `Z()`, `T()` and `Px()`, `Py()`,
-`Pz()` and `E()`. Both sets return the same values but the first set is
-more relevant for use where **`TLorentzVector`** describes a combination
-of position and time and the second set is more relevant where
-**`TLorentzVector`** describes momentum and energy:
-
-``` {.cpp}
-   Double_t xx =v.X();
-...
-   Double_t tt = v.T();
-   Double_t px = v.Px();
-...
-   Double_t ee = v.E();
-```
-
-The components of **`TLorentzVector`** can also accessed by index:
-
-``` {.cpp}
-   xx = v(0);orxx = v[0];
-   yy = v(1);yy = v[1];
-   zz = v(2);zz = v[2];
-   tt = v(3);tt = v[3];
-```
-
-You can use the `Vect()` method to get the vector component of
-**`TLorentzVector`**:
-
-``` {.cpp}
-   TVector3 p = v.Vect();
-```
-
-For setting components there are two methods: `SetX(),.., SetPx(),..:`
-
-``` {.cpp}
-   v.SetX(1.); orv.SetPx(1.);
-......
-   v.SetT(1.);v.SetE(1.);
-```
-
-To set more the one component by one call you can use the `SetVect()`
-function for the **`TVector3`** part or `SetXYZT()`, `SetPxPyPzE()`. For
-convenience there is also a `SetXYZM()`:
-
-``` {.cpp}
-   v.SetVect(TVector3(1,2,3));
-   v.SetXYZT(x,y,z,t);
-   v.SetPxPyPzE(px,py,pz,e);
-   v.SetXYZM(x,y,z,m);   // v = (x,y,z,e = Sqrt(x*x+y*y+z*z+m*m))
-```
-
-### Vector Components in Non-Cartesian Coordinates
-
-
-There are a couple of methods to get and set the **`TVector3`** part of
-the parameters in `spherical` coordinate systems:
-
-``` {.cpp}
-   Double_t m, theta, cost, phi, pp, pp2, ppv2, pp2v2;
-   m = v.Rho();
-   t = v.Theta();
-   cost = v.CosTheta();
-   phi  = v.Phi();
-   v.SetRho(10.);
-   v.SetTheta(TMath::Pi()*.3);
-   v.SetPhi(TMath::Pi());
-```
-
-or get information about the r-coordinate in cylindrical systems:
-
-``` {.cpp}
-   Double_t pp, pp2, ppv2, pp2v2;
-   pp   = v.Perp();     // get transverse component
-   pp2  = v.Perp2();    // get transverse component squared
-   ppv2 = v.Perp(v1);   // get transverse component with respect
-                        // to another vector
-   pp2v2 = v.Perp(v1);
-```
-
-there are two more set functions `SetPtEtaPhiE(pt,eta,phi,e)` and
-`SetPtEtaPhiM(pt,eta,phi,m)` for convenience.
-
-### Arithmetic and Comparison Operators
-
-
-The **`TLorentzVector`** class provides operators to add subtract or
-compare four-vectors:
-
-``` {.cpp}
-   v3 = -v1;
-   v1 = v2+v3;
-   v1+= v3;
-   v1 = v2 + v3;
-   v1-= v3;
-   if (v1 == v2) {...}
-   if (v1 != v3) {...}
-```
-
-### Magnitude/Invariant mass, beta, gamma, scalar product
-
-
-The scalar product of two four-vectors is calculated with the
-`(-,-,-,+) `metric:
-
-**`s = v1*v2 `** `= t1*t2-x1*x2-y1*y2-z1*z2 `
-
-The magnitude squared `mag2` of a four-vector is therefore:
-
-**`mag2 = v*v`** ` = t*t-x*x-y*y-z*z `
-
-If `mag2` is negative: **`mag = -Sqrt(-mag*mag)`**. The methods are:
-
-``` {.cpp}
-   Double_t s, s2;
-   s  = v1.Dot(v2);// scalar product
-   s  = v1*v2;// scalar product
-   s2 = v.Mag2();ors2 = v.M2();
-   s  = v.Mag();s  = v.M();
-```
-
-Since in case of momentum and energy the magnitude has the meaning of
-invariant mass **`TLorentzVector`** provides the more meaningful aliases
-`M2()` and `M()`. The methods `Beta()` and `Gamma()` returns `beta` and
-`gamma = 1/Sqrt(1-beta*beta)`.
-
-### Lorentz Boost
-
-
-A boost in a general direction can be parameterized with three
-parameters which can be taken as the components of a three vector
-`b=(bx,by,bz)`. With `x=(x,y,z)` and `gamma=1/Sqrt(1-beta*beta)` (beta
-being the module of vector b)`,` an arbitrary active Lorentz boost
-transformation (from the rod frame to the original frame) can be written
-as:
-
-`x = x' + (gamma-1)/(beta*beta)*(b*x')*b + gamma*t'*b `
-
-`t = gamma(t'+ b*x') `
-
-The `Boost()` method performs a boost transformation from the rod frame
-to the original frame. `BoostVector()` returns a **`TVector3`** of the
-spatial components divided by the time component:
-
-``` {.cpp}
-   TVector3 b;
-   v.Boost(bx,by,bz);
-   v.Boost(b);
-   b = v.BoostVector();// b=(x/t,y/t,z/t)
-```
-
-### Rotations
-
-
-There are four sets of functions to rotate the **`TVector3`** component
-of a **`TLorentzVector`**:
-
-Around Axes:
-
-``` {.cpp}
-   v.RotateX(TMath::Pi()/2.);
-   v.RotateY(.5);
-   v.RotateZ(.99);
-```
-
-Around an arbitrary axis:
-
-``` {.cpp}
-   v.Rotate(TMath::Pi()/4., v1); // rotation around v1
-```
-
-Transformation from rotated frame:
-
-``` {.cpp}
-   v.RotateUz(direction); // direction must be a unit TVector3
-```
-
-Rotation by **`TRotation`**:
-
-``` {.cpp}
-   TRotation r;
-   v.Transform(r);//or v *= r;  (v = r*v)
-```
-
-### Miscellaneous
-
-
-Angle between two vectors:
-
-``` {.cpp}
-   Double_t a = v1.Angle(v2);// get angle between v1 and v2
-```
-
-Methods `Plus()` and `Minus()` return the positive and negative
-light-cone components:
-
-``` {.cpp}
-   Double_t pcone = v.Plus();
-   Double_t mcone = v.Minus();
-```
-
-A general Lorentz transformation (see class `TLorentzRotation)` can be
-used by the `Transform()` method, the `*=, or *` operator of the
-**`TLorentzRotation`** class:
-
-``` {.cpp}
-   TLorentzRotation l;
-   v.Transform(l);
-   v = l*v;orv *= l;// v = l*v
-```
-
-## TLorentzRotation
-
-
-The **`TLorentzRotation`** class describes Lorentz transformations
-including Lorentz boosts and rotations (see **`TRotation`**)
-
-$$
-lambda =
-\left|
-\begin{array}{cccc}
-         xx  &  xy  & xz & xt \\
-         yx  &  yy  & yz & yt \\
-         zx  &  zy  & zz & zt \\
-         tx  &  ty  & tz & tt
-\end{array}
-\right|
-$$
-
-### Declaration
-
-
-By default it is initialized to the identity matrix, but it may also be
-initialized by other **`TLorentzRotation`**, by a pure **`TRotation`**
-or by a boost:
-
-``` {.cpp}
-   TLorentzRotation l;   // l is initialized as identity
-   TLorentzRotation m(l);// m = l
-   TRotation r;
-   TLorentzRotation lr(r);
-   TLorentzRotation lb1(bx,by,bz);
-   TVector3 b;
-   TLorentzRotation lb2(b);
-```
-
-The Matrix for a Lorentz boosts is:
-
-$$
-\left|
-\begin{array}{cccc}
-1+gamma'*bx*bx &    gamma'*bx*by &    gamma'*bx*bz  & gamma*bx \\
-  gamma'*bx*bz &  1+gamma'*by*by &    gamma'*by*by  & gamma*by \\
-  gamma'*bz*bx &    gamma'*bz*by &  1+gamma'*bz*bz  & gamma*bz \\
-  gamma*bx     &    gamma*by     &    gamma*bz      & gamma
-\end{array}
-\right|
-$$
-
-with the boost vector `b=(bx,by,bz)`;
-`gamma=1/Sqrt(1-beta*beta)`;` gamma'=(gamma-1)/beta*beta.`
-
-### Access to the Matrix Components/Comparisons
-
-
-The access to the matrix components is possible with the methods `XX()`,
-`XY()` ... `TT()`, and with the operator` (int,int)`:
-
-``` {.cpp}
-   Double_t xx;
-   TLorentzRotation l;
-   xx = l.XX();              // gets the xx component
-   xx = l(0,0);              // gets the xx component
-   if (l == m) {...}         // test for equality
-   if (l != m) {...}         // test for inequality
-   if (l.IsIdentity()) {...} // test for identity
-```
-
-### Transformations of a Lorentz Rotation
-
-
-There are four possibilities to find the product of two
-**`TLorentzRotation`** transformations:
-
-``` {.cpp}
-   TLorentzRotation a,b,c;
-   c = b*a;                       // product
-   c = a.MatrixMultiplication(b); // a is unchanged
-   a *= b;                        // a=a*b
-   c = a.Transform(b)             // a=b*a then c=a
-```
-
-Lorentz boosts:
-
-``` {.cpp}
-   Double_t bx, by, bz;
-   TVector3 v(bx,by,bz);
-   TLorentzRotation l;
-   l.Boost(v);
-   l.Boost(bx,by,bz);
-```
-
-Rotations:
-
-``` {.cpp}
-   TVector3 axis;
-   l.RotateX(TMath::Pi()); // rotation around x-axis
-   l.Rotate(.5,axis);      // rotation around specified vector
-```
-
-Inverse transformation: use the method `Inverse() `to return the inverse
-transformation keeping the current one unchanged`.` The method
-`Invert()` inverts the current **`TLorentzRotation`**:
-
-``` {.cpp}
-   l1 = l2.Inverse(); // l1 is inverse of l2, l2 unchanged
-   l1 = l2.Invert();  // invert l2, then  l1=l2
-```
-
-The matrix for the inverse transformation of a **`TLorentzRotation`** is
-as follows:
-
-$$
-\left|
-\begin{array}{cccc}
-         xx  &  xy  & xz & -tx \\
-         yx  &  yy  & yz & -ty \\
-         zx  &  zy  & zz & -tz \\
-         -xt  &  -yt  & -zt & tt
-\end{array}
-\right|
-$$
-
-### Transformation of a TLorentzVector
-
-
-To apply **`TLorentzRotation`** to **`TLorentzVector`** you can use
-either the `VectorMultiplication()` method or the `* operator`. You can
-also use the `Transform()` function and the `*= `operator of the class
-**`TLorentzVector`**.
-
-``` {.cpp}
-   TLorentzVector v;
-   TLorentzRotation l;
-...
-   v = l.VectorMultiplication(v);
-   v = l * v;
-   v.Transform(l);
-   v *= l;            // v = l*v
-```
-
-### Physics Vector Example
-
-
-The test file `$ROOTSYS/test/TestVectors.cxx is` an example of using
-physics vectors. The vector classes are not loaded by default, and to
-run it, you will need to load `libPhysics.so` first:
-
-``` {.cpp}
-root[] .L $ROOTSYS/lib/libPhysics.so
-root[] .x TestVectors.cxx
-```
-
-To load the physics vector library in a ROOT application use:
-
-``` {.cpp}
-   gSystem->Load("libPhysics");
-```
-
-The example `$ROOTSYS/test/TestVectors.cxx` does not return much,
-especially if all went well, but when you look at the code you will find
-examples for many calls.
diff --git a/documentation/users-guide/Preface.md b/documentation/users-guide/Preface.md
deleted file mode 100644
index 00aa1c20174aa..0000000000000
--- a/documentation/users-guide/Preface.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# Preface {.unnumbered}
-
-In late 1994, we decided to learn
-and investigate Object Oriented programming and C++ to better judge
-the suitability of these relatively new techniques for scientific
-programming. We knew that there is no better way to learn a new
-programming environment than to use it to write a program that can
-solve a real problem. After a few weeks, we had our first
-histogramming package in C++. A few weeks later we had a rewrite of
-the same package using the, at that time, very new template features
-of C++. Again, a few weeks later we had another rewrite of the package
-without templates since we could only compile the version with
-templates on one single platform using a specific compiler. Finally,
-after about four months we had a histogramming package that was faster
-and more efficient than the well-known FORTRAN based HBOOK
-histogramming package. This gave us enough confidence in the new
-technologies to decide to continue the development. Thus was born
-ROOT. Since its first public release at the end of 1995, ROOT has
-enjoyed an ever-increasing popularity. Currently it is being used in
-all major High Energy and Nuclear Physics laboratories around the
-world to monitor, to store and to analyse data. In the other sciences
-as well as the medical and financial industries, many people are using
-ROOT. We estimate the current user base to be around several thousand
-people. In 1997, Eric Raymond analysed in his paper "The Cathedral and
-the Bazaar" the development method that makes Linux such a success.
-The essence of that method is: "release early, release often and
-listen to your customers". This is precisely how ROOT is being
-developed. Over the last five years, many of our "customers" became
-co-developers. Here we would like to thank our main co-developers and
-contributors:
-
-**Masaharu Goto** wrote the C++ interpreter CINT that was an
-essential part of ROOT before ROOT 6. Despite being 8 time zones ahead
-of us, we have the feeling he has been sitting in the room next door
-since 1995.
-
-**Andrei** and **Mihaela Gheata** (Alice collaboration) are co-authors
-of the ROOT geometry classes and Virtual Monte-Carlo. They have been
-working with the ROOT team since 2000.
-
-**Olivier Couet**, who after a successful development and maintenance
-of PAW, has joined the ROOT team in 2000 and has been working on the
-graphics sub-system.
-
-**Ilka Antcheva** has been working on the Graphical User Interface
-classes. She is also responsible for this latest edition of the Users
-Guide with a better style, improved index and several new chapters
-(since 2002).
-
-**Bertrand Bellenot** has been developing and maintaining the Win32GDK
-version of ROOT. Bertrand has also many other contributions like the
-nice RootShower example (since 2001).
-
-**Valeriy Onoutchin** has been working on several ROOT packages, in
-particular the graphics sub-system for Windows and the GUI Builder
-(since 2000).
-
-**Gerri Ganis** has been working on the authentication procedures to
-be used by the root daemons and the PROOF system (since 2002).
-
-**Maarten Ballintijn** (MIT) is one of the main developers of the
-PROOF sub-system (since 1995).
-
-**Valeri Fine** (now at BNL) ported ROOT to Windows and contributed
-largely to the 3-D graphics. He is currently working on the Qt layer
-of ROOT (since 1995).
-
-**Victor Perevoztchikov** (BNL) worked on key elements of the I/O
-system, in particular the improved support for STL collections
-(1997-2001).
-
-**Nenad Buncic** developed the HTML documentation generation system
-and integrated the X3D viewer inside ROOT (1995-1997).
-
-**Suzanne Panacek** was the author of the first version of this User's
-Guide and very active in preparing tutorials and giving lectures about
-ROOT (1999-2002).
-
-**Axel Naumann** has been developing further the HTML Reference Guide
-and helps in porting ROOT under Windows (cygwin/gcc implementation)
-(since 2000).
-
-**Anna Kreshuk** has developed the Linear Fitter and Robust Fitter
-classes as well as many functions in TMath, TF1, TGraph (since 2005).
-
-**Richard Maunder** has contributed to the GL viewer classes (since
-2004).
-
-**Timur Pocheptsov** has contributed to the GL viewer classes and GL
-in pad classes (since 2004).
-
-**Sergei Linev** has developed the XML driver and the TSQLFile classes
-(since 2003).
-
-**Stefan Roiser** has been contributing to the reflex and cintex
-packages (since 2005).
-
-**Lorenzo Moneta** has been contributing the MathCore, MathMore,
-Smatrix & Minuit2 packages (since 2005).
-
-**Wim Lavrijsen** is the author of the PyRoot package (since 2004).
-
-Further we would like to thank all the people mentioned in the
-`$ROOTSYS/README/CREDITS` file for their contributions, and finally,
-everybody who gave comments, reported bugs and provided fixes.
-
-Happy ROOTing!
-
-Rene Brun & Fons Rademakers
-
-Geneva, July 2007
-
diff --git a/documentation/users-guide/PythonRuby.md b/documentation/users-guide/PythonRuby.md
deleted file mode 100644
index 4a7fde2158e55..0000000000000
--- a/documentation/users-guide/PythonRuby.md
+++ /dev/null
@@ -1,934 +0,0 @@
-# Python Interface
-\index{Python}
-
-Python is a popular, open-source, dynamic programming language with an
-interactive interpreter. Its interoperability with other programming
-languages, both for extending Python as well as embedding it, is
-excellent and many existing third-party applications and libraries have
-therefore so-called "Python bindings." PyROOT provides Python bindings
-for ROOT: it enables cross-calls from ROOT/Cling into Python and vice
-versa, the intermingling of the two interpreters, and the transport of
-user-level objects from one interpreter to the other. PyROOT enables
-access from ROOT to any application or library that itself has Python
-bindings, and it makes all ROOT functionality directly available from
-the python interpreter.
-
-## PyROOT Overview
-
-The Python scripting language is widely used for scientific programming,
-including high performance and distributed parallel code (see
-<http://www.scipy.org>). It is the second most popular scripting
-language (after Perl) and enjoys a wide-spread use as a "glue language":
-practically every library and application these days comes with Python
-bindings (and if not, they can be easily written or generated).
-
-`PyROOT`, a Python extension module, provides the bindings for the ROOT
-class library in a generic way using the Cling dictionary. This way, it
-allows the use of any ROOT classes from the Python interpreter, and thus
-the "glue-ing" of ROOT libraries with any non-ROOT library or
-applications that provide Python bindings. Further, `PyROOT` can be
-loaded into the Cling interpreter to allow (as of now still rudimentary)
-access to Python classes. The best way to understand the benefits of
-`PyROOT` is through a few examples.
-
-### Glue-ing Applications
-
-The `PyQt` library, see <http://www.riverbankcomputing.co.uk/pyqt>,
-provides Python bindings for the Qt cross-platform GUI framework (
-<http://www.trolltech.com>). With `PyROOT` and `PyQt`, adding ROOT
-application layer code to a Qt GUI, becomes children play. The following
-example shows how a Python class can be used to have ROOT code respond
-to a click on a Qt widget.
-
-``` {.cpp}
-# Glue-ing Qt and ROOT through Python
-import sys, ROOT
-from qt import *
-
-theApp = QApplication( sys.argv)
-box = QVBox()
-box.resize(QSize(40,10).expandedTo(box.minimumSizeHint()))
-
-class myButton(QPushButton):
-    def __init__( self,label,master):
-        QPushButton.__init__(self,label,master)
-        self.setFont( QFont('Times',18,QFont.Bold))
-
-    def browse(self):
-        self.b = ROOT.TBrowser()
-
-bb = myButton('browser',box)
-QObject.connect( bb,SIGNAL('clicked()'),bb.browse)
-
-theApp.setMainWidget(box)
-box.show()
-theApp.exec_loop()
-```
-
-When the example is run, a Qt button is displayed, and when the button
-is clicked, a **`TBrowser`** instance is created and will appear on the
-screen. `PyROOT` takes care of feeding system events to ROOT widgets, so
-the **`TBrowser`** instance and the button behave properly when users
-interact with them.
-
-### Access to ROOT from Python
-
-There are several tools for scientific analysis that come with bindings
-that allow the use of these tools from the Python interpreter. `PyROOT`
-provides this for users who want to do analysis in Python with ROOT
-classes. The following example shows how to fill and display a ROOT
-histogram while working in Python. Of course, any actual analysis code
-may come from somewhere else through other bindings, e.g. from a C++
-program.
-
-When run, the next example will display a 1-dimensional histogram
-showing a Gaussian distribution. More examples like the one above are
-distributed with ROOT under the `$ROOTSYS/tutorials` directory.
-
-``` {.cpp}
-# Example: displaying a ROOT histogram from Python
-from ROOT import gRandom,TCanvas,TH1F
-
-c1 = TCanvas('c1','Example',200,10,700,500)
-hpx = TH1F('hpx','px',100,-4,4)
-
-for i in xrange(25000):
-    px = gRandom.Gaus()
-    hpx.Fill(px)
-
-hpx.Draw()
-c1.Update()
-```
-
-### Access to Python from ROOT
-
-Access to Python objects from Cling is not completely fleshed out.
-Currently, ROOT objects and built-in types can cross the boundary
-between the two interpreters, but other objects are much more
-restricted. For example, for a Python object to cross, it has to be a
-class instance, and its class has to be known to Cling first (i.e. the
-class has to cross first, before the instance can). All other
-cross-coding is based on strings that are run on the Python interpreter
-and vise-versa.
-
-With the ROOT v4.00/06 and later, the **`TPython`** class will be loaded
-automatically on use, for older editions, the `libPyROOT.so` needs to be
-loaded first before use. It is possible to switch between interpreters
-by calling **`TPython::Prompt()`** on the ROOT side, while returning with
-`^D` (`EOF`). State is preserved between successive switches, and string
-based cross calls can nest as long as shared resources are properly
-handled.
-
-``` {.cpp}
-// Example: accessing the Python interpreter from ROOT
-// either load PyROOT explicitly or rely on auto-loading
-root[] gSystem->Load( "libPyROOT" );
-root[] TPython::Exec("print1+1");
-2
-
-// create a TBrowser on the Python side, and transfer it back and forth
-root[] TBrowser* b = (void*)TPython::Eval("ROOT.TBrowser()");
-(class TObject*)0x8d1daa0
-root[] TPython::Bind(b,"b");
-
-// builtin variables can cross-over (after the call i==2)
-root[] int i = TPython::Eval( "1+1" );
-root[] i
-(int)2
-```
-
-### Installation
-
-There are several ways of obtaining `PyROOT`, and which is best depends
-on your specific situation. If you work at CERN, you can use the
-installation available on `afs`. Otherwise, you will want to build from
-source, as `PyROOT` is not build by default in the binaries distributed
-from the ROOT project site. If you download the ROOT binaries, take care
-to download and install the Python distribution from
-<http://www.python.org/> against which they were built.
-
-#### Environment Settings
-
-ROOT installations with the build of `PyROOT` enabled are available from
-the CERN `afs` cell `/afs/cern.ch/sw/root/<version>/<platform>`. To use
-them, simply modify your shell environment accordingly. For Unix:
-
-`export PATH=$ROOTSYS/bin:$PYTHONDIR/bin:$PATH`
-
-`export LD_LIBRARY_PATH=$ROOTSYS/lib:$PYTHONDIR/lib:$LD_LIBRARY_PATH`
-
-`export PYTHONPATH=$ROOTSYS/lib:$PYTHONPATH`
-
-For Windows:
-
-`set PATH=%ROOTSYS%/bin;%PYTHONDIR%/bin;%PATH%`
-
-`set PYTHONPATH=%ROOTSYS%/bin;%PYTHONPATH%`
-
-where `$ROOTSYS` should be set to
-`/afs/cern.ch/sw/root/<version>/<platform>`, and `PYTHONDIR` to
-`/afs/cern.ch/sw/lcg/external/Python/2.3.4/<platform>` with `<version>`
-and `<platform>` as appropriate. Note that the latest version of Python
-is 2.4.1.
-
-#### Building from Source
-
-The standard installation instructions for building ROOT from source
-apply, with the addition that the build of `PyROOT` needs to be enabled
-at the configuration step. First, follow the instructions for obtaining
-and unpacking the source, and setting up the build environment.
-
-Then, use the following command to configure the build process (of
-course, feel free to add any additional flags you may need):
-
-`$ ./configure <arch> [--with-python-incdir=<dir>][--with-python-libdir=>dir>]`
-
-For details on `<arch>` see the official build pages, the Python include
-directory should point to the directory that contains `Python.h` and the
-library directory should point to the directory containing
-`libpythonx.y.so`, where '`x`' and '`y`' are the major and minor version
-number, respectively. If you do not specify include and library
-directories explicitly, the configuration process will try the
-`PYTHONDIR` environment variable or, alternatively, the standard
-locations.
-
-A recent distribution of Python is required: version 2.4.3 is preferred,
-but the older 2.2.x and 2.3.x versions suffice and are supported as
-well. Versions older than 2.2 are not supported and will not work. Note
-that one problem with 2.2 is that the shared library of the `Python`
-interpreter core is not build by default and the '--enable-shared' flag
-should thus be used when building `Python` from source. If the `Python`
-interpreter that is installed on your system is too old, please obtain a
-new version from <http://www.python.org>.
-
-Once configured, you continue the build process the normal way:
-
-`$ make`
-
-`$ make install`
-
-After some time, a library called `libPyROOT.so` (or `libPyROOT.dll`, on
-Windows) will be created in the
-`$ROOTSYS/lib `(`$ROOTSYS/bin on Windows`) directory and a top Python
-module, `ROOT.py`, will be copied into the same place. The final step is
-to setup the shell environment, which is similar to what is described in
-the chapter ‘Environment Settings'. Note that the `$ROOTSYS` entries are
-probably already there if you followed the standard instructions, and
-that the `PYTHONDIR` entries should be replaced as appropriate by your
-choice at configuration time, or be left out if you had the
-configuration script pick up them up from a default location.
-
-### Using PyROOT
-
-Since it is an extension module, the usage of `PyROOT` probably comes
-naturally if you're used to Python. In general, `PyROOT` attempts to
-allow working in both Python and ROOT style, and although it is
-succeeding, it isn't perfect: there are edges. The following sections
-explain in some detail what you can expect, and what you need to watch
-out for.
-
-#### Access to ROOT Classes
-
-Before a ROOT class can be used from Python, its dictionary needs to be
-loaded into the current process. Starting with ROOT version 4.00/06,
-this happens automatically for all classes that are declared to the
-auto-loading mechanism through so-called `rootmap` files. Effectively,
-this means that all classes in the ROOT distributions are directly
-available for import. For example:
-
-``` {.cpp}
-from ROOT import TCanvas          # available at startup
-c = TCanvas()
-
-from ROOT import TLorentzVector   # triggers auto-load of libPhysics
-l = TLorentzVector()
-```
-
-Although it is not recommended, a simple way of working with `PyROOT` is
-doing a global import:
-
-``` {.cpp}
-from ROOT import *
-
-c = TCanvas()
-l = TLorentzVector()
-```
-
-Keeping the ROOT namespace ("`import ROOT`"), or only importing from
-ROOT those classes that you will actually use (see above), however, will
-always be cleaner and clearer:
-
-``` {.cpp}
-import ROOT
-
-c = ROOT.TCanvas()
-l = ROOT.TLorentzVector()
-```
-
-Since it is foreseen that most people will use the simple approach
-anyway, the request to copy all from module ROOT will not actually
-result in copying all ROOT classes into the current namespace. Instead,
-classes will still be bound (and possibly loaded) on an as-needed basis.
-Note carefully how this is different from other Python (extension)
-modules, and what to expect if you use the normal inspection tools (such
-as e.g. '`dir()`'). This feature prevents the inspection tools from
-being swamped by an enormous amount of classes, but they can no longer
-be used to explore unknown parts of the system (e.g. to find out which
-classes are available). Furthermore, because of this approach,
-\<`tab`\>-completion will usually not be available until after the first
-use (and hence creation) of a class.
-
-Access to class static functions, public data members, enums, etc. is as
-expected. Many more example uses of ROOT classes from Python can be
-found in the tutorials directory in the ROOT distribution. The recipes
-section contains a description on working with your own classes (see
-"Using Your Own Classes").
-
-#### Access to STL Classes
-
-The STL classes live in the ROOT.std namespace (or, if you prefer to get
-them from there, in the ROOT module directly, but doing so makes the
-code less clear, of course). Be careful in their use, because Python
-already has types called "`string`" and "`list`."
-
-In order to understand how to get access to a templated class, think of
-the general template as a meta class. By instantiating the meta class
-with the proper parameters, you get an actual class, which can then be
-used to create object instances. An example usage:
-
-``` {.cpp}
->>> from ROOT import std
->>> v = std.vector(int)()
->>> for i in range(0,10):
-...    v.push_back(i)
-...
->>> for i in v:
-...     print(i, end=' ')
-1 2 3 4 5 6 7 8 9
->>>
->>> list(v)
-[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
->>>
-```
-
-The parameters to the template instantiation can either be an actual
-type or value (as is used here, "int"), or a string representation of
-the parameters (e.g. "'double'"), or a mixture of both (e.g. "'TCanvas,
-0'" or "'double', 0" ). The "std::vector\<int\>" class is one of the
-classes builtin by default into the Cling extension dlls. You will get a
-non-functional class (instances of which can still be passed around to
-C++) if the corresponding dictionary doesn't exist.
-
-#### Access to ROOT Globals
-
-Most globals and global functions can be imported directly from the
-ROOT.py module, but some common ones (most notably **`gMinuit`**,
-although that variable now exists at startup from release 5.08 onward)
-do not exist yet at program startup, as they exist in modules that are
-loaded later (e.g. through the auto-loading mechanism). An example
-session should make this clear:
-
-``` {.cpp}
->>> from ROOT import *
->>> gROOT                              # directly available
-<ROOT.TROOT object at 0x399c30>
->>> gMinuit                            # library not yet loaded: not available
-Traceback (most recent call last):
-File "<stdin>", line 1, in ?
-NameError: name 'gMinuit' is not defined
->>> TMinuit                            # use of TMinuit class forces auto-loading
-<class '__main__.TMinuit'>
->>> gMinuit                            # now gMinuit is available
-<__main__.TMinuit object at 0x1458c70>
->>> not not gMinuit                    # but it is the null pointer, until set
-False
->>> g = TMinuit()
->>> not not gMinuit
-True
-```
-
-It is also possible to create globals interactively, either by executing
-a Cling macro, or by a call to `gROOT.ProcessLine()`. These globals are
-made available in the same way: either use them directly after creation
-in 'from ROOT import \*' more, or get them from the ROOT namespace after
-an 'import ROOT'.
-
-As of 5.08, the behaviour of ROOT globals is the same as python globals,
-which is sometimes counterintuitive: since they are references, they can
-be changed only if done so directly through their containing module. The
-following session shows that in detail:
-
-``` {.cpp}
->>> from ROOT import *
->>> print(gDebug)
-0
->>> gROOT.ProcessLine( 'gDebug = 7;' )
->>> print(gDebug)
-0                                 # local gDebug is unchanged
->>> gDebug = 5                    # changes _local_ reference only
->>> print(gDebug)
-5                                 # locally correct, but ...
->>> gROOT.ProcessLine( 'cout << gDebug << endl;' )
-7                                 # ... ROOT global unchanged
->>> import ROOT
->>> print(ROOT.gDebug)
-7                                 # still the old value (not '5')
->>> ROOT.gDebug = 3               # changes ROOT module reference
->>> gROOT.ProcessLine( 'cout << gDebug << endl;' )
-3                                 # ROOT global properly changed
->>>
-```
-
-The above is another good reason to prefer 'import ROOT' over 'from ROOT
-import \*'.
-
-#### Access to Python
-
-The access to Python from Cling goes through the **`TPython`** class, or
-directly if a Python object or class has crossed the border. The
-**`TPython`** class, which looks approximately like this:
-
-``` {.cpp}
-class TPython {
-
-public:
-   // load a Python script as if it were a macro
-    static void LoadMacro(const char* name);
-
-   // execute a Python statement (e.g. "import ROOT")
-    static void Exec(const char* cmd);
-
-   // evaluate a Python expression (e.g. "1+1")
-    static const TPyReturn& Eval(const char* expr);
-
-   // bind a ROOT object with, at the Python side, the name "label"
-    static bool Bind(TObject* obj,const char* label);
-
-   // enter an interactive Python session (exit with ^D)
-    static void Prompt();
-};
-```
-
-`LoadMacro(const char* name)` - the argument is a name of a Python file
-that is to be executed (`'execfile'`), after which any new classes are
-automatically made available to Cling. Since it is non-selective, use
-with care.
-
-`ExecScript(const char* name,int argc=0,const char** argv=0)` - the
-argument is a name of a python file that is to be executed ('execfile')
-in a private namespace to minimize side-effects. Optionally, you can add
-CLI-style arguments which are handed to the script through 'sys.argv' in
-the normal way.
-
-`Exec(const char* cmd) `- the argument is a string of Python code that
-is executed as a statement. There is no return value, but an error
-message will be printed if there are problems such as syntax errors.
-
-`Eval(const char* expr) `- the argument is a string of Python code that
-is evaluated as an expression. The result of the expression is returned,
-if it is either a builtin type (int, long, float, double, and
-`const char*` are supported), a Python type that can cross, or a ROOT
-type. If a ROOT type is returned, an explicit cast to void\* is needed
-to assign the return value to a local pointer (which may have a
-different type), whereas builtin types will be cast implicitly, if
-possible, to the type of the local variable to which they are assigned.
-
-`Bind(TObject* obj,const char* label)` - transfer a ROOT object from the
-Cling to the Python interpreter, where it will be referenced with a
-variable called "`label`".
-
-`Prompt()` - Transfer the interactive prompt to Python.
-
-With the ROOT v4.00/06 and later, the **`TPython`** class will be loaded
-automatically on use, for older editions, the `libPyROOT.so` needs to be
-loaded first with `gSystem->Load()` before use. Refer back to the other
-example of the use of **`TPython`** that was given in "Access to Python
-from ROOT".
-
-To show in detail how Python access can be used, an example Python
-module is needed, as follows:
-
-``` {.cpp}
-print('creating class MyPyClass ... ')
-class MyPyClass:
-    def __init__(self):
-        print('in MyPyClass.__init__')
-        self._browser = None
-    def gime(self, what):
-        return what
-```
-
-This module can now be loaded into a Cling session, the class used to
-instantiate objects, and their member functions called for showing how
-different types can cross:
-
-``` {.cpp}
-root[] TPython::LoadMacro("MyPyClass.py");
-creating class MyPyClass ...
-root[] MyPyClass m;
-in MyPyClass.__init__
-root[] char* s = m.gime("aap");
-root[] s
-(char* 0x41ee7754)"aap"
-```
-
-Note that the `LoadMacro()` call makes the class automatically
-available, such that it can be used directly. Otherwise, a
-`gROOT->GetClass()` call is required first.
-
-#### Callbacks
-
-The simplest way of setting a callback to Python from Cling, e.g. for a
-button, is by providing the execution string. See for example
-`tutorials/demo.py` that comes with the ROOT installation:
-
-``` {.cpp}
-# [..]
-bar = ROOT.TControlBar('vertical','Demos')
-bar.AddButton('Help on Demos',r'TPython::Exec("execfile('demoshelp.py')");','Click Here For Help on Running the Demos')
-bar.AddButton('browser',r'TPython::Exec("b = Tbrowser()");','Start the ROOT browser')
-# [..]
-```
-
-Here, the callback is a string that will be interpreted by Cling to call
-`TPython::Exec()`, which will, in turn, interpret and execute the string
-given to it. Note the use of raw strings (the '`r`' in front of the
-second argument string), in order to remove the need of escaping the
-backslashes.
-
-#### Cling Commands
-
-In interactive mode, the Python exception hook is used to mimic some of
-the Cling commands available. These are: `.q`, **`.!`**, **`.x`**,
-**`.L`**, **`.cd`**, **`.ls`**, **`.pwd`**, **`.?`** and **`.help`**.
-Note that **`.x`** translates to Python '`execfile()`' and thus accepts
-only Python files, not Cling macros.
-
-### Memory Handling
-
-The Python interpreter handles memory for the user by employing
-reference counting and a garbage collector (for new-style objects, which
-includes `PyROOT` objects). In C++, however, memory handling is done
-either by hand, or by an application specific, customized mechanism (as
-is done in ROOT). Although `PyROOT` is made aware of ROOT memory
-management, there are still a few boundary conditions that need to be
-dealt with by hand. Also, the heuristics that `PyROOT` employs to deal
-with memory management are not infallible. An understanding in some
-detail of the choices that are made is thus important.
-
-#### Automatic Memory Management
-
-There are two global policies that can be set: heuristics and strict. By
-default, the heuristic policy is used, in which the following rules are
-observed:
-
--   A ROOT object created on the Python interpreter side is owned by
-    Python and will be deleted once the last Python reference to it goes
-    away. If, however, such an object is passed by non-const address as
-    a parameter to a C++ function (with the exception of the use as
-    "self" to a member function), ownership is relinquished.
-
--   A ROOT object coming from a ROOT call is not owned, but before it
-    passes to the Python interpreter, its "must cleanup" bit is set if
-    its type is a class derived from **`TObject`**. When the object goes
-    out of scope on the C++ side, the Python object will change type
-    into an object that largely behaves like None.
-
-The strict policy differs in that it will never relinquish ownership
-when passing an object as a parameter to a function. It is then up to
-the developer to prevent double deletes. Choosing one or the other
-policy is done by:
-
-``` {.cpp}
-ROOT.SetMemoryPolicy( ROOT.kMemoryStrict )
-```
-
-for the strict policy, or for the heuristic policy:
-
-``` {.cpp}
-ROOT.SetMemoryPolicy( ROOT.kMemoryHeuristics )
-```
-
-Care must be taken in the case of graphic objects: when drawn on the
-current pad, a reference to the graphics is kept that `PyROOT` isn't
-currently aware of, and it is up to the developer to keep at lease one
-Python reference alive. See `$ROOTSYS/tutorials/pyroot/zdemo.py`
-(available in the latest release) for an example. Alternatively, one can
-tell python to give up ownership for individual instances:
-
-``` {.cpp}
-o = ROOT.TObject()
-ROOT.SetOwnership( o, False )      # True to own, False to release
-```
-
-#### Memory Management by Hand
-
-If needed, you can explicitly destroy a ROOT object that you own through
-its associated **`TClass`**:
-
-``` {.cpp}
-myobject.IsA().Destructor(myobject)
-```
-
-which will send out the deletion notification to the system (thus you do
-not need to care anymore at this point about Python reference counting,
-the object will go, even if it's reference count it non-zero), and free
-the memory.
-
-### Performance
-
-The performance of `PyROOT` when programming with ROOT in Python is
-similar to that of Cling. Differences occur mainly because of differences
-in the respective languages: C++ is much harder to parse, but once
-parsed, it is much easier to optimize. Consequently, individual calls to
-ROOT are typically faster from `PyROOT`, whereas loops are typically
-slower.
-
-When programming in Python, the modus operandi is to consider
-performance generally "good enough" on the outset, and when it turns out
-that, it is not good enough; the performance critical part is converted
-into C/C++ in an extension module. The school of thought where
-pre-mature optimization is the root of all evil should find this way of
-working very satisfying. In addition, if you look at their history, you
-will see that many of the standard Python modules have followed this
-path.
-
-Your code should always make maximum use of ROOT facilities; such that
-most of the time is spending in compiled code. This goes even for very
-simple things: e.g. do not compute invariant masses in Python, use
-**`TLorentzVector`** instead. Moreover, before you start optimizing,
-make sure that you have run a profiler to find out where the bottlenecks
-are. Some performance, without cost in terms of programmer effort, may
-be gained by using `psyco`, see the next link:
-<http://psyco.sourceforge.net>, a Python just in time compiler (JIT).
-Note, however, that `psyco` is limited to Intel i386 CPUs. Since `psyco`
-optimizes Python, not `PyROOT` calls; it generally does not improve
-performance that much if most of your code consists of ROOT API calls.
-Mathematical computations in Python, on the other hand, benefit a lot.
-
-Every call to a Python member function results in a lookup of that
-member function and an association of this method with `'self'`.
-Furthermore, a temporary object is created during this process that is
-discarded after the method call. In inner loops, it may be worth your
-while (up to 30%), to short-cut this process by looking up and binding
-the method before the loop, and discarding it afterwards. Here is an
-example:
-
-``` {.cpp}
-hpx = TH1F('hpx','px',100,-4,4)
-hpxFill = hpx.Fill                # cache bound method
-for i in xrange(25000):
-    px = gRandom.Gaus()
-hpxFill(px)                    # use bound method: no lookup needed
-del hpxFill                       # done with cached method
-```
-
-Note that if you do not discard the bound method, a reference to the
-histogram will remain outstanding, and it will not be deleted when it
-should be. It is therefore important to delete the method when you're
-done with it.
-
-### Use of Python Functions
-
-It is possible to mix Python functions with ROOT and perform such
-operations as plotting and fitting of histograms with them. In all
-cases, the procedure consists of instantiating a ROOT **`TF1`**,
-**`TF2`**, or **`TF3`** with the Python function and working with that
-ROOT object. There are some memory issues, so it is for example not yet
-possible to delete a **`TF1`** instance and then create another one with
-the same name. In addition, the Python function, once used for
-instantiating the **`TF1`**, is never deleted.
-
-Instead of a Python function, you can also use callable instances (e.g.,
-an instance of a class that has implemented the `__call__` member
-function). The signature of the Python callable should provide for one
-or two arrays. The first array, which must always be present, shall
-contain the `x`, `y`, `z`, and t values for the call. The second array,
-which is optional and its size depends on the number given to the
-**`TF1`** constructor, contains the values that parameterize the
-function. For more details, see the **`TF1`** documentation and the
-examples below.
-
-#### Plotting Python Function
-
-This is an example of a parameter less Python function that is plotted
-on a default canvas:
-
-``` {.cpp}
-from ROOT import TF1, TCanvas
-
-def identity( x ):
-    return x[0]
-
-# create an identity function
-f = TF1('pyf1', identity, -1., 1.)
-
-# plot the function
-c = TCanvas()
-f.Draw()
-```
-
-Because no number of parameters is given to the **`TF1`** constructor,
-'`0`' (the default) is assumed. This way, the '`identity'` function need
-not handle a second argument, which would normally be used to pass the
-function parameters. Note that the argument '`x`' is an array of size 4.
-The following is an example of a parameterized Python callable instance
-that is plotted on a default canvas:
-
-``` {.cpp}
-from ROOT import TF1, TCanvas
-
-class Linear:
-    def __call__( self, x, par ):
-        return par[0] + x[0]*par[1]
-
-# create a linear function with offset 5, and pitch 2
-f = TF1('pyf2',Linear(),-1.,1.,2)
-f.SetParameters(5.,2.)
-
-# plot the function
-c = TCanvas()
-f.Draw()
-```
-
-Note that this time the constructor is told that there are two
-parameters, and note in particular how these parameters are set. It is,
-of course, also possible (and preferable if you only use the function
-for plotting) to keep the parameters as data members of the callable
-instance and use and set them directly from Python.
-
-#### Fitting Histograms
-
-Fitting a histogram with a Python function is no more difficult than
-plotting: instantiate a **`TF1`** with the Python callable and supply
-that **`TF1`** as a parameter to the `Fit()` member function of the
-histogram. After the fit, you can retrieve the fit parameters from the
-**`TF1`** instance. For example:
-
-``` {.cpp}
-from ROOT import TF1, TH1F, TCanvas
-
-class Linear:
-    def __call__( self, x, par ):
-        return par[0] + x[0]*par[1]
-
-# create a linear function for fitting
-f = TF1('pyf3',Linear(),-1.,1.,2)
-
-# create and fill a histogram
-h = TH1F('h','test',100,-1.,1.)
-f2 = TF1('cf2','6.+x*4.5',-1.,1.)
-h.FillRandom('cf2',10000)
-
-# fit the histo with the python 'linear' function
-h.Fit(f)
-
-# print results
-par = f.GetParameters()
-print('fit results: const =', par[0], ',pitch =', par[1])
-```
-
-### Working with Trees
-
-Next to making histograms, working with trees is probably the most
-common part of any analysis. The **`TTree`** implementation uses
-pointers and dedicated buffers to reduce the memory usage and to speed
-up access. Consequently, mapping **`TTree`** functionality to Python is
-not straightforward, and most of the following features are implemented
-in ROOT release 4.01/04 and later only, whereas you will need 5.02 if
-you require all of them.
-
-#### Accessing an Existing Tree
-
-Let us assume that you have a file containing **`TTrees`**,
-**`TChains`**, or **`TNtuples`** and want to read the contents for use
-in your analysis code. This is commonly the case when you work with the
-result of the reconstruction software of your experiment (e.g. the
-combined ntuple in ATLAS). The following example code outlines the main
-steps (you can run it on the result of the `tree1.C` macro):
-
-``` {.cpp}
-from ROOT import TFile
-
-# open the file
-myfile = TFile('tree1.root')
-
-# retrieve the ntuple of interest
-mychain = myfile.Get('t1')
-entries = mychain.GetEntriesFast()
-
-for jentry in xrange(entries):
-    # get the next tree in the chain and verify
-    ientry = mychain.LoadTree(jentry)
-    if ientry < 0:
-        break
-
-    # copy next entry into memory and verify
-    nb = mychain.GetEntry(jentry)
-    if nb<=0:
-        continue
-
-    # use the values directly from the tree
-    nEvent = int(mychain.ev)
-    if nEvent<0:
-        continue
-
-    print(mychain.pz, '=', mychain.px*mychain.px, '+', mychain.py*mychain.py)
-```
-
-Access to arrays works the same way as access to single value tree
-elements, where the size of the array is determined by the number of
-values actually read from the file. For example:
-
-``` {.cpp}
-# loop over array tree element
-for d in mychain.mydoubles:
-    print(d)
-
-# direct access into an array tree element
-i5 = mychain.myints[5]
-```
-
-#### Writing a Tree
-
-Writing a ROOT **`TTree`** in a Python session is a little convoluted,
-if only because you will need a C++ class to make sure that data members
-can be mapped, unless you are working with built-in types. Here is an
-example for working with the latter only:
-
-``` {.cpp}
-from ROOT import TFile, TTree
-from array import array
-
-h = TH1F('h1','test',100,-10.,10.)
-f = TFile('test.root','recreate')
-t = TTree('t1','tree with histos')
-maxn = 10
-n = array('i',[0])
-d = array('f',maxn*[0.])
-t.Branch('mynum',n,'mynum/I')
-t.Branch('myval',d,'myval[mynum]/F')
-
-for i in range(25):
-    n[0] = min(i,maxn)
-    for j in range(n[0]):
-        d[j] = i*0.1+j
-        t.Fill()
-
-f.Write()
-f.Close()
-```
-
-The use of arrays is needed, because the pointer to the address of the
-object that is used for filling must be given to the **`TTree::Branch()`**
-call, even though the formal argument is declared a '`void*'`. In the
-case of ROOT objects, similar pointer manipulation is unnecessary,
-because the full type information is available, and `TTree::Branch()`
-has been Pythonized to take care of the call details. However, data
-members of such objects that are of built-in types, still require
-something extra since they are normally translated to Python primitive
-types on access and hence their address cannot be taken. For that
-purpose, there is the `AddressOf()` function. As an example:
-
-``` {.cpp}
-from ROOT import TFile, TTree
-from ROOT import gROOT, AddressOf
-
-gROOT.ProcessLine(
-"struct MyStruct { Int_t fMyInt1; Int_t fMyInt2; Int_t fMyInt3; Char_t fMyCode[4]; };" );
-
-from ROOT import MyStruct
-mystruct = MyStruct()
-f = TFile('mytree.root','RECREATE')
-tree = TTree('T','Just A Tree')
-tree.Branch('myints',mystruct,'MyInt1/I:MyInt2:MyInt3')
-tree.Branch('mycode',AddressOf(mystruct,'fMyCode'),'MyCode/C')
-for i in range(0,10):
-    mystruct.fMyInt1 = i
-    mystruct.fMyInt2 = i*i
-    mystruct.fMyInt3 = i*i*i
-    mystruct.fMyCode = "%03d" % i      # note string assignment
-
-    tree.Fill()
-
-f.Write()
-f.Close()
-```
-
-The C++ class is defined through the `gROOT.ProcessLine()` call, and
-note how the `AddressOf()` function is used for data members of built-in
-type. Most of the above is for ROOT version 5.02 and later only. For
-older releases, and without further support, here is an example as to
-how you can get hold of a pointer-to-pointer to a ROOT object:
-
-``` {.cpp}
-h = TH1F()
-addressofobject = array('i',[h.IsA().DynamicCast(h.IsA(),h)])
-```
-
-### Using Your Own Classes
-
-A user's own classes can be accessed after loading, either directly or
-indirectly, the library that contains the dictionary. One easy way of
-obtaining such a library, is by using ACLiC:
-
-``` {.cpp}
-$ cat MyClass.C
-class MyClass {
-public:
-
-MyClass(int value = 0) {
-m_value = value;
-}
-
-void SetValue(int value) {
-m_value = value;
-}
-
-int GetValue() {
-return m_value;
-}
-
-private:
-    int m_value;
-};
-
-$ echo .L MyClass.C+ | root.exe -b
-[...]
-Info in <TUnixSystem::ACLiC>: creating shared library [..]/./MyClass_C.so
-$
-```
-
-Then you can use it, for example, like so:
-
-``` {.cpp}
-from ROOT import gSystem
-
-# load library with MyClass dictionary
-gSystem.Load('MyClass_C')
-
-# get MyClass from ROOT
-from ROOT import MyClass
-# use MyClass
-m = MyClass(42)
-print(m.GetValue())
-```
-
-You can also load a macro directly, but if you do not use ACLiC, you
-will be restricted to use the default constructor of your class, which
-is otherwise fully functional. For example:
-
-``` {.cpp}
-from ROOT import gROOT
-
-# load MyClass definition macro (append '+' to use ACLiC)
-gROOT.LoadMacro('MyClass.C')
-
-# get MyClass from ROOT
-from ROOT import MyClass
-
-# use MyClass
-m = MyClass()
-m.SetValue(42)
-print(m.GetValue())
-```
diff --git a/documentation/users-guide/ROOTUsersGuide.ist b/documentation/users-guide/ROOTUsersGuide.ist
deleted file mode 100644
index 264cd2c47d903..0000000000000
--- a/documentation/users-guide/ROOTUsersGuide.ist
+++ /dev/null
@@ -1,6 +0,0 @@
-heading_prefix "{\\bfseries\\hfil "
-heading_suffix "\\hfil}\\nopagebreak\n"
-headings_flag 1
-delim_0 "\\dotfill"
-delim_1 "\\dotfill"
-delim_2 "\\dotfill"
diff --git a/documentation/users-guide/ROOTUsersGuide.md b/documentation/users-guide/ROOTUsersGuide.md
deleted file mode 100644
index 61297bd1a35a1..0000000000000
--- a/documentation/users-guide/ROOTUsersGuide.md
+++ /dev/null
@@ -1,3 +0,0 @@
-% ![](pictures/rootlogo.png)
-% User's Guide
-% May 2018
diff --git a/documentation/users-guide/SignalSlot.md b/documentation/users-guide/SignalSlot.md
deleted file mode 100644
index a896547c0c1f7..0000000000000
--- a/documentation/users-guide/SignalSlot.md
+++ /dev/null
@@ -1,179 +0,0 @@
-# The Signal/Slot Communication Mechanism
-\index{Signal/Slot}
-
-## Introduction
-
-ROOT supports its own version of the signal/slot communication mechanism originally featured in **Qt**, a C++ GUI application framework by [the Qt Company.](https://www.qt.io/) The ROOT implementation uses the ROOT type system. In addition to all features provided by Qt the ROOT version supports connecting slots to a class (as opposed to connecting to a specific object). These slots will be called whenever the specified signal is emitted by any object of the class. Also a slot can have default arguments and be either a class method or a stand-alone function (compiled or interpreted).
-
-## Basic Concepts
-
-Signals and slots are used for communication between objects.
-
-Signals are emitted by objects when they change their state in a way that may be interesting to the outside world. This is all the object does to communicate. It does not know if anything is receiving the signal at the other end.
-
-Slots can be used for receiving signals. A slot does not know if it has any signal(s) connected to it.
-
-This is true information encapsulation, and ensures that the object can be used as a true software component.
-
-Signals and slots can take any number of arguments of any type.
-
-It is possible to connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you desire.
-
-It is possible to make a single connection from all objects of the same class.
-
-## A Small Example
-
-A minimal C++ class declaration might read:
-
-``` {.cpp}
-class A {
-private:
-   Int_t  fValue;
-public:
-   A() { fValue = 0; }
-   Int_t  GetValue() const { return fValue; }
-   void   SetValue(Int_t);
-};
-```
-
-A small ROOT **interpreted** class might read:
-
-``` {.cpp}
-class A {
-   RQ_OBJECT("A")
-private:
-    Int_t  fValue;
-public:
-    A() { fValue = 0; }
-    Int_t  GetValue() const { return fValue; }
-    void   SetValue(Int_t);      //*SIGNAL*
-};
-```
-
-This class has the same internal state, and public methods to access the state, but in addition it has support for component programming using signals. This class can tell the outside world that its state has changed by emitting a signal, `SetValue(Int_t)`.
-
-Here is a possible implementation of `A::SetValue()`:
-
-``` {.cpp}
-void A::SetValue(Int_t v)
-{
-   if (v != fValue) {
-      fValue = v;
-      Emit("SetValue(Int_t)", v);
-   }
-}
-```
-
-The line `Emit("SetValue(Int_t)", v)` emits the signal `SetValue(Int_t)` with argument `v` from the object. As you can see, you emit a signal by using `Emit("full_method_name",arguments)`.
-
-Here is one of the ways to connect two of these objects together:
-
-``` {.cpp}
-A *a = new A();
-A *b = new A();
-a->Connect("SetValue(Int_t)", "A", b, "SetValue(Int_t)");
-b->SetValue(11);
-a->SetValue(79);
-b->GetValue();          // this would now be 79, why?
-```
-
-The statement `a->Connect("SetValue(Int_t)", "A", b, "SetValue(Int_t)")`  denotes that object `a` connects its `"SetValue(Int_t)"` signal to `"A::SetValue(Int_t)"` method of object `b`.
-
-Calling `a->SetValue(79)` will make `a` emit a signal, which `b` will receive, i.e. `b->SetValue(79)` is invoked. It is executed immediately, just like a normal function call. `b` will in turn emit the same signal, which nobody receives, since no slot has been connected to it, so it disappears into hyperspace.
-
-This example illustrates that objects can work together without knowing about each other, as long as there is someone around to set up a connection between them.
-
-## Features of the ROOT implementation
-
-* The ROOT implementation **does not require the** *moc* preprocessor and the `signal:` and `slot:` keywords in the class declaration. Signals and slots are normal class methods.
-
-* The class which corresponds to **Qt's** **QObject** is [TQObject](https://root.cern/doc/master/classTQObject.html). It reproduces the general features of the QObject class and has the `Connect()`, `Disconnect()` and `Emit()` methods. The [TQObject](https://root.cern/doc/master/classTQObject.html) class does not derive from any class which makes it possible to have multiple inheritance from [TObject](https://root.cern/doc/master/classTQObject.html) derived classes and [TQObject](https://root.cern/doc/master/classTQObject.html).
-
-* By placing the [`RQ_OBJECT()`](https://root.cern/doc/master/RQ__OBJECT_8h.html) macro inside a class body you can use signals and slots with classes not inheriting from [TQObject](https://root.cern/doc/master/classTQObject.html), like interpreted classes which can not derive from compiled classes. This makes it possible to apply the **Object Communication Mechanism** between compiled and interpreted classes in an interactive ROOT session.
-
-* The ROOT implementation allows to make connections to any object known to the ROOT C++ interpreter. The following line makes a connection between signal `Pressed()` from `button` and method/slot `Draw()` from object `hist` of class (compiled or interpreted) `TH1`
-
-    ``` {.cpp}
-    Connect(button, "Pressed()", "TH1", hist, "Draw()");
-    ```
-
-    To connect to a stand-alone function (compiled or interpreted) the arguments corresponding to the name of the class and receiving object should be zero. For example
-
-    ``` {.cpp}
-    Connect(button, "Pressed()", 0, 0, "printInfo()");
-    ```
-
-* It is also possible to make a single connection from all objects of the same class. For example:
-
-    ``` {.cpp}
-    TQObject::Connect("Channel", "AlarmOn()", "HandlerClass", handler, "HandleAlarm()");
-    ```
-
-    where the class name is specified by the first argument. Signal `"AlarmOn()"` for any object of class `"Channel"` is now connected to the `"HandleAlarm()"` method of the `"handler"` object of the `"HandlerClass"`.
-
-* It is possible to set default parameters values to a slot method while connecting to it. Such slot will be activated without passing parameters to it. To set default arguments to a slot an equal symbol '=' should be placed at the beginning of the prototype string. For example
-
-     ``` {.cpp}
-     Connect(button, "Pressed()", "TH1", hist, "SetMaximum(=123)");
-     Connect(button, "Pressed()", "TH1", hist, "Draw(=\"LEGO\")");
-     ```
-
-## Signals
-
-A signal is a normal class method. **The first requirement** is that it should call an `Emit()` method. The format of this method is the following:
-
-``` {.cpp}
-Emit("full_method_name"[,arguments]);
-```
-
-where `"full_method_name"` is the method name and prototype string of the signal method.
-For example, for `SetValue(Int_t value)` the full method name will be `"SetValue(Int_t)"`, where `SetValue` is the method name and `Int_t` the prototype string. Note that typedefs will be resolved to facilitate matching of slots to signals. So the slot `"print(int)"` can be connected to the above signal which has an `Int_t` as argument.
-
-**The second requirement** is that the method declaration should have the string `*SIGNAL*` in its comment field. Like:
-
-``` {.cpp}
-void SetValue(Int_t x);  //*SIGNAL*
-```
-
-This provides an explicit interface specification for the user (this requirement is currently not enforced at run-time).
-
-**The third requirement**, only necessary if you want to have class signals (i.e. for all objects of a class), is that you have to replace the standard `ClassImp` macro by `ClassImpQ`.
-
-Signals are currently implemented for all ROOT GUI classes and the [TTimer](https://root.cern/doc/master/classTTimer.html) and [TCanvas](https://root.cern/doc/master/classTCanvas.html) classes (to find quickly all defined signals do for example: `grep '*SIGNAL*' $ROOTSYS/include/*.h`).
-
-## Examples
-
-### A First Time Example ([rqfirst.C](http://root.cern.ch/root/rqex/rqfirst.C))
-
-This example shows:
-
-*   How to create interpreted class with signals with different types/number of arguments.
-*   How to connect signals to slots.
-*   How to activate signals.
-
-### Histogram Filling with Dynamic State Reported via Signals ([rqsimple.C](http://root.cern.ch/root/rqex/rqsimple.C))
-
-Based on hsimple this example demonstrates:
-
-*   All features of the hsimple example.
-*   How to create an interpreted class with signals which will report about dynamic state of the histogram processing.
-*   How to use the [TTimer](https://root.cern/doc/master/classTTimer.html) class for emulation of "multithreading".
-*   How to use signals for the concurrent update of pad, file, benchmark facility, etc.
-
-### An Example on How to Use Canvas Event Signals ([rqfiller.C](http://root.cern.ch/root/rqex/rqfiller.C))
-
-This example shows:
-
-*   How the object communication mechanism can be used for handling the [TCanvas](https://root.cern/doc/master/classTCanvas.html)'s mouse/key events in an interpreted class.
-
-With this demo you can fill histograms by hand:
-
-*   Click the left button or move mouse with button pressed to fill histograms.
-*   Use the right button of the mouse to reset the histograms.
-
-### Complex GUI Using Signals and Slots ([guitest.C](https://root.cern.ch/doc/master/guitest_8C.html))
-
-Based on `$ROOTSYS/test/guitest.cxx` this example demonstrates:
-
-*   All features of the original compiled guitest.cxx program.
-*   Sophisticated use of signals and slots to build a complete user interface that can be executed either in the interpreter or as a compiled program.
diff --git a/documentation/users-guide/Threads.md b/documentation/users-guide/Threads.md
deleted file mode 100644
index 514d2c54b3e2a..0000000000000
--- a/documentation/users-guide/Threads.md
+++ /dev/null
@@ -1,685 +0,0 @@
-# Threads
-
-
-A thread is an independent flow of control that operates within the same
-address space as other independent flows of controls within a process.
-In most UNIX systems, thread and process characteristics are grouped
-into a single entity called a process. Sometimes, threads are called
-"lightweight processes''.
-
-Note: This introduction is adapted from the AIX 4.3 Programmer's Manual.
-
-## Threads and Processes
-
-
-In traditional single-threaded process systems, a process has a set of
-properties. In multi-threaded systems, these properties are divided
-between processes and threads.
-
-### Process Properties
-
-
-A process in a multi-threaded system is the changeable entity. It must
-be considered as an execution frame. It has all traditional process
-attributes, such as:
-
--   Process ID, process group ID, user ID, and group ID
-
--   Environment
-
--   Working directory
-
-A process also provides a common address space and common system
-resources:
-
--   File descriptors
-
--   Signal actions
-
--   Shared libraries
-
--   Inter-process communication tools (such as message queues, pipes,
-    semaphores, or shared memory)
-
-### Thread Properties
-
-
-A thread is the schedulable entity. It has only those properties that
-are required to ensure its independent flow of control. These include
-the following properties:
-
--   Stack
-
--   Scheduling properties (such as policy or priority)
-
--   Set of pending and blocked signals
-
--   Some thread-specific data (TSD)
-
-An example of thread-specific data is the error indicator, `errno`. In
-multi-threaded systems, `errno` is no longer a global variable, but
-usually a subroutine returning a thread-specific `errno` value. Some
-other systems may provide other implementations of `errno`. With respect
-to ROOT, a thread specific data is for example the ***`gPad`*** pointer,
-which is treated in a different way, whether it is accessed from any
-thread or the main thread.
-
-Threads within a process must not be considered as a group of processes
-(even though in Linux each thread receives an own process id, so that it
-can be scheduled by the kernel scheduler). All threads share the same
-address space. This means that two pointers having the same value in two
-threads refer to the same data. Also, if any thread changes one of the
-shared system resources, all threads within the process are affected.
-For example, if a thread closes a file, the file is closed for all
-threads.
-
-### The Initial Thread
-
-
-When a process is created, one thread is automatically created. This
-thread is called the initial thread or the main thread. The initial
-thread executes the main routine in multi-threaded programs.
-
-Note: At the end of this chapter is a glossary of thread specific terms
-
-## Implementation of Threads in ROOT
-
-
-The **`TThread`** class has been developed to provide a platform
-independent interface to threads for ROOT.
-
-### Installation
-
-
-For the time being, it is still necessary to compile a threaded version
-of ROOT to enable some very special treatments of the canvas operations.
-We hope that this will become the default later.
-
-To compile ROOT, just do (for example on a debian Linux):
-
-```
-./configure linuxdeb2 --with-thread=/usr/lib/libpthread.so
-gmake depend
-gmake
-```
-
-This configures and builds ROOT using `/usr/lib/libpthread.so` as the
-`Pthread` library, and defines `R__THREAD`.
-
-This enables the thread specific treatment of *`gPad`*, and creates
-`$ROOTSYS/lib/libThread.so.`
-
-Note: The parameter linuxdeb2 has to be replaced with the appropriate
-ROOT keyword for your platform.
-
-### Classes
-
-
-**`TThread`** class implements threads . The platform dependent
-implementation is in the **`TThreadImp`** class and its descendant
-classes (e.g. **`TPosixThread`** ).
-
-**`TMutex`** class implements `mutex` locks. A mutex is a mutually
-exclusive lock. The platform dependent implementation is in the
-**`TMutexImp`** class and its descendant classes (e.g.
-**`TPosixMutex`**)
-
-**`TCondition`** class implements a condition variable. Use a condition
-variable to signal threads. The platform dependent implementation is in
-the **`TConditionImp`** and **`TPosixCondition`** classes .
-
-**`TSemaphore`** class implements a counting semaphore. Use a semaphore
-to synchronize threads. The platform dependent implementation is in the
-**`TMutexImp`** and **`TConditionImp`** classes.
-
-### TThread for Pedestrians
-
-
-To run a thread in ROOT, follow these steps:
-
-1. Initialization
-
-Add these lines to your `rootlogon.C`:
-
-``` {.cpp}
-{
-   ...
-   // The next line may be unnecessary on some platforms
-   gSystem->Load("/usr/lib/libpthread.so");
-   gSystem->Load("$ROOTSYS/lib/libThread.so");
-   ...
-}
-```
-
-This loads the library with the **`TThread`** class and the `pthread`
-specific implementation file for `Posix` threads.
-
-2. Coding
-
-Define a function (e.g. `void* UserFun(void* UserArgs))` that should run
-as a thread. The code for the examples is at the web site of the authors
-(Jörn Adamczewski, Marc Hemberger). After downloading the code from this
-site, you can follow the example below:
-
-<http://www-linux.gsi.de/~go4/HOWTOthreads/howtothreadsbody.html>
-
-3. Loading
-
-Start an interactive ROOT session. Load the shared library:
-
-``` {.cpp}
-root[] gSystem->Load("mhs3.so");              // or
-root[] gSystem->Load("CalcPiThread.so");
-```
-
-4. Creating
-
-Create a thread instance (see also example `RunMhs3.C `or` RunPi.C`)
-with:
-
-``` {.cpp}
-root[] TThread *th = new TThread(UserFun,UserArgs);
-```
-
-When called from the interpreter, this gives the name "`UserFun`" to the
-thread. This name can be used to retrieve the thread later. However,
-when called from compiled code, this method does not give any name to
-the thread. So give a name to the thread in compiled use:
-
-``` {.cpp}
-root[] TThread *th = new TThread("MyThread", UserFun, UserArgs);
-```
-
-You can pass arguments to the thread function using the
-`UserArgs`-pointer. When you want to start a method of a class as a
-thread, you have to give the pointer to the class instance as
-`UserArgs`.
-
-5. Running
-
-``` {.cpp}
-root[] th->Run();
-root[] TThread::Ps(); // like UNIX ps c.ommand;
-```
-
-With the `mhs3` example, you should be able to see a canvas with two
-pads on it. Both pads keep histograms updated and filled by three
-different threads. With the `CalcPi` example, you should be able to see
-two threads calculating Pi with the given number of intervals as
-precision.
-
-### TThread in More Details
-
-
-Cling is not thread safe yet, and it will block the execution of the
-threads until it has finished executing.
-
-#### Asynchronous Actions
-
-Different threads can work simultaneously with the same object. Some
-actions can be dangerous. For example, when two threads create a
-histogram object, ROOT allocates memory and puts them to the same
-collection. If it happens at the same time, the results are
-undetermined. To avoid this problem, the user has to synchronize these
-actions with:
-
-``` {.cpp}
-   TThread::Lock()    // Locking the following part of code
-   ...                // Create an object, etc...
-   TThread::UnLock()  // Unlocking
-```
-
-The code between `Lock()` and `UnLock()` will be performed
-uninterrupted. No other threads can perform actions or access
-objects/collections while it is being executed. The methods
-`TThread::Lock() `and **`TThread::UnLock()`** internally use a global
-`TMutex` instance for locking.
-
-The user may also define their own **`TMutex`** `MyMutex` instance and may
-locally protect their asynchronous actions by calling `MyMutex.Lock()` and
-`MyMutex.UnLock().`
-
-#### Synchronous Actions: TCondition
-
-To synchronize the actions of different threads you can use the
-**`TCondition`** class, which provides a signaling mechanism. The
-**`TCondition`** instance must be accessible by all threads that need to
-use it, i.e. it should be a global object (or a member of the class
-which owns the threaded methods, see below). To create a
-**`TCondition`** object, a **`TMutex`** instance is required for the
-Wait and `TimedWait` locking methods. One can pass the address of an
-external mutex to the **`TCondition`** constructor:
-
-``` {.cpp}
-   TMutex MyMutex;
-   TCondition MyCondition(&MyMutex);
-```
-
-If zero is passed, **`TCondition`** creates and uses its own internal
-mutex:
-
-``` {.cpp}
-   TCondition MyCondition(0);
-```
-
-You can now use the following methods of synchronization:
-
--   `TCondition::Wait()` waits until any thread sends a signal of the
-    same condition instance: `MyCondition.Wait()` reacts on
-    `MyCondition.Signal()` or `MyCondition.Broadcast()`.
-    `MyOtherCondition.Signal()` has no effect.
-
--   If several threads wait for the signal from the same
-    **`TCondition`** `MyCondition`, at `MyCondition.Signal()` only one
-    thread will react; to activate a further thread another
-    `MyCondition.Signal()` is required, etc.
-
--   If several threads wait for the signal from the same
-    **`TCondition`** `MyCondition`, at `MyCondition.Broadcast()` all
-    threads waiting for `MyCondition` are activated at once.
-
-In some tests of `MyCondition` using an internal mutex, `Broadcast()`
-activated only one thread (probably depending whether `MyCondition` had
-been signaled before).
-
--   `MyCondition.TimedWait(secs,nanosecs)` waits for `MyCondition` until
-    the *absolute* time in seconds and nanoseconds since beginning of
-    the epoch (January, 1st, 1970) is reached; to use relative timeouts
-    ‘‘delta'', it is required to calculate the absolute time at the
-    beginning of waiting ‘‘now''; for example:
-
-``` {.cpp}
-   Ulong_t now,then,delta;                   // seconds
-   TDatime myTime;                           // root daytime class
-   myTime.Set();                             // myTime set to "now"
-   now=myTime.Convert();                     // to seconds since 1970
-```
-
--   Return value wait of `MyCondition.TimedWait` should be 0, if
-    `MyCondition.Signal()` was received, and should be nonzero, if
-    timeout was reached.
-
-The conditions example shows how three threaded functions are
-synchronized using **`TCondition`**: a ROOT script `condstart.C` starts
-the threads, which are defined in a shared library
-(`conditions.cxx, conditions.h`).
-
-#### Xlib Connections
-
-Usually `Xlib` is not thread safe. This means that calls to the X could
-fail, when it receives X-messages from different threads. The actual
-result depends strongly on which version of `Xlib` has been installed on
-your system. The only thing we can do here within ROOT is calling a
-special function `XInitThreads() `(which is part of the `Xlib`), which
-should (!) prepare the `Xlib` for the usage with threads.
-
-To avoid further problems within ROOT some redefinition of the
-***`gPad`*** pointer was done (that's the main reason for the
-recompilation). When a thread creates a **`TCanvas`**, this object is
-actually created in the main thread; this should be transparent to the
-user. Actions on the canvas are controlled via a function, which returns
-a pointer to either thread specific data (TSD) or the main thread
-pointer. This mechanism works currently only for ***`gPad`***,
-***`gDirectory`***, ***`gFile`*** and will be implemented soon for other
-global Objects as e.g. ***`gVirtualX`***.
-
-#### Canceling a TThread
-
-Canceling of a thread is a rather dangerous action. In **`TThread`**
-canceling is forbidden by default. The user can change this default by
-calling `TThread::SetCancelOn()`. There are two cancellation modes:
-deferred and asynchronous.
-
-#### Deferred
-
-Set by `TThread::SetCancelDeferred()` (default): When the user knows
-safe places in their code where a thread can be canceled without risk for
-the rest of the system, they can define these points by invoking
-**`TThread`**`::CancelPoint()`. Then, if a thread is canceled, the
-cancellation is deferred up to the call of
-**`TThread`**`::CancelPoint()` and then the thread is canceled safely.
-There are some default cancel points for `pthreads` implementation, e.g.
-any call of the `TCondition::Wait()`, **`TCondition`**`::TimedWait()`,
-`TThread::Join()`.
-
-#### Asynchronous
-
-Set by `TThread::SetCancelAsynchronous()`: If the user is sure that
-their application is cancel safe, they could call:
-
-``` {.cpp}
-   TThread::SetCancelAsynchronous();
-   TThread::SetCancelOn();
-   // Now cancelation in any point is allowed.
-   ...
-   // Return to default
-   TThread::SetCancelOff();
-   TThread::SetCancelDeferred();
-```
-
-To cancel a thread `TThread* th` call:
-
-``` {.cpp}
-   th->Kill();
-```
-
-To cancel by thread name:
-
-``` {.cpp}
-   TThread::Kill(name);
-```
-
-To cancel a thread by ID:
-
-``` {.cpp}
-   TThread::Kill(tid);
-```
-
-To cancel a thread and delete `th` when cancel finished:
-
-``` {.cpp}
-   th->Delete();
-```
-
-Deleting of the thread instance by the operator delete is dangerous. Use
-`th->Delete()` instead. C++ delete is safe only if thread is not
-running. Often during the canceling, some clean up actions must be
-taken. To define clean up functions use:
-
-``` {.cpp}
-   void UserCleanUp(void *arg) {
-      // here the user cleanup is done
-      ...
-   }
-   TThread::CleanUpPush(&UserCleanUp,arg);
-          // push user function into cleanup stack"last in, first out"
-   TThread::CleanUpPop(1); // pop user function out of stack and
-                        // execute it, thread resumes after this call
-   TThread::CleanUpPop(0); // pop user function out of stack
-   // _without_ executing it
-```
-
-Note: `CleanUpPush` and `CleanUpPop` should be used as corresponding
-pairs like brackets; unlike `pthreads` cleanup stack (which is *not*
-implemented here), **`TThread`** does not force this usage.
-
-#### Finishing thread
-
-When a thread returns from a user function the thread is finished. It
-also can be finished by `TThread::Exit()`. Then, in case of
-`thread`-detached mode, the thread vanishes completely. By default, on
-finishing **`TThread`** executes the most recent cleanup function
-(`CleanUpPop(1)` is called automatically once).
-
-## Advanced TThread: Launching a Method in a Thread
-
-
-Consider a class `Myclass` with a member function that shall be launched
-as a thread.
-
-``` {.cpp}
-   void* Myclass::Thread0((void* arg)
-```
-
-To start Thread0 as a **`TThread`**, class `Myclass` may provide a
-method:
-
-``` {.cpp}
-Int_t Myclass::Threadstart(){
-   if(!mTh){
-      mTh= new TThread("memberfunction",
-                 (void(*)(void *))&Thread0,(void*) this);
-      mTh->Run();
-      return 0;
-   }
-   return 1;
-}
-```
-
-Here `mTh` is a `TThread*` pointer which is member of `Myclass `and
-should be initialized to 0 in the constructor. The **`TThread`**
-constructor is called as when we used a plain C function above, except
-for the following two differences.
-
-First, the member function Thread0 requires an explicit cast to
-`(void(*) (void *)`). This may cause an annoying but harmless compiler
-warning:
-
-``` {.cpp}
-Myclass.cxx:98: warning:
-              converting from "void (Myclass::*)(void *)"to "void *" )
-```
-
-Strictly speaking, `Thread0` must be a static member function to be
-called from a thread. Some compilers, for example `gcc` version 2.95.2,
-may not allow the `(void(*) (void*))s` cast and just stop if `Thread0`
-is not static. On the other hand, if `Thread0` is static, no compiler
-warnings are generated at all. Because the `'this'` pointer is passed in
-`'arg'` in the call to `Thread0(void *arg),` you have access to the
-instance of the class even if `Thread0` is static. Using the `'this'`
-pointer, non static members can still be read and written from
-`Thread0`, as long as you have provided Getter and Setter methods for
-these members. For example:
-
-``` {.cpp}
-   Bool_t state = arg->GetRunStatus();
-   arg->SetRunStatus(state);
-```
-
-Second, the pointer to the current instance of `Myclass`, i.e. (void\*)
-this, has to be passed as first argument of the threaded function
-Thread0 (C++ member functions internally expect this pointer as first
-argument to have access to class members of the same instance).
-`pthreads` are made for simple C functions and do not know about Thread0
-being a member function of a class. Thus, you have to pass this
-information by hand, if you want to access all members of the `Myclass`
-instance from the Thread0 function.
-
-Note: Method Thread0 cannot be a virtual member function, since the cast
-of `Thread0` to `void(*)` in the **`TThread`** constructor may raise
-problems with C++ virtual function table. However, Thread0 may call
-another virtual member function virtual void `Myclass::Func0()` which
-then can be overridden in a derived class of `Myclass`. (See example
-`TMhs3`).
-
-Class `Myclass` may also provide a method to stop the running thread:
-
-``` {.cpp}
-Int_t Myclass::Threadstop() {
-   if (mTh) {
-      TThread::Delete(mTh);
-      delete mTh;
-      mTh=0;
-      return 0;
-   }
-   return 1;
-}
-```
-
-Example `TMhs3:` Class **`TThreadframe`**
-(`TThreadframe.h, TThreadframe.cxx`) is a simple example of a framework
-class managing up to four threaded methods. Class `TMhs3`
-(`TMhs3.h, TMhs3.cxx)` inherits from this base class, showing the `mhs3`
-example 8.1 `(mhs3.h, mhs3.cxx) `within a class. The `Makefile` of this
-example builds the shared libraries `libTThreadframe.so` and
-`libTMhs3.so`. These are either loaded or executed by the ROOT script
-`TMhs3demo.C,` or are linked against an executable: `TMhs3run.cxx`.
-
-### Known Problems
-
-
-Parts of the ROOT framework, like the interpreter, are not yet
-thread-safe. Therefore, you should use this package with caution. If you
-restrict your threads to distinct and \`simple' duties, you will able to
-benefit from their use. The **`TThread`** class is available on all
-platforms, which provide a POSIX compliant thread implementation. On
-Linux, Xavier Leroy's Linux Threads implementation is widely used, but
-the **`TThread`** implementation should be usable on all platforms that
-provide `pthread`.
-
-**Linux Xlib on SMP machines** is not yet thread-safe. This may cause
-crashes during threaded graphics operations; this problem is independent
-of ROOT.
-
-**Object instantiation:** there is no implicit locking mechanism for
-memory allocation and global ROOT lists. The user has to explicitly
-protect their code when using them.
-
-## The Signals of ROOT
-
-
-The list of default signals handled by ROOT is:
-
-``` {.cpp}
-kSigChildkSigPipe
-kSigBuskSigAlarm
-kSigSegmentationViolationkSigUrgent
-kSigIllegalInstructionkSigFloatingException
-kSigSystemkSigWindowChanged
-```
-
-The signals ***`kSigFloatingException`***,
-***`kSigSegmentationViolation`***, ***`kSigIllegalInstruction`***, and
-***`kSigBus`*** cause the printing of the ***`*** Break *** `*** message
-and make a long jump back to the ROOT prompt. No other custom
-**`TSignalHandler`** can be added to these signals.
-
-The ***`kSigAlarm`*** signal handles asynchronous timers. The
-***`kSigWindowChanged`*** signal handles the resizing of the terminal
-window. The other signals have no other behavior then that to call any
-registered **`TSignalHandler`*****`::Notify()`***.
-
-When building in interactive application the use of the **`TRint`**
-object handles the `kSigInterrupt` signal. It causes the printing of the
-message: ***`*** Break *** keyboard interrupt `***and makes a long jump
-back to the ROOT command prompt. If no **`TRint`** object is created,
-there will be no `kSigInterrupt` handling. All signals can be reset to
-their default UNIX behavior via the call of
-**`TSytem`**`::ResetSignal()`. All signals can be ignored via
-`TSytem::IgnoreSignal()`. The **`TSytem::IgnoreInterrupt()`** is a method
-to toggle the handling of the interrupt signal. Typically it is called
-to prevent a `SIGINT` to interrupt some important call (like writing to
-a ROOT file).
-
-If **`TRint`** is used and the default ROOT interrupt handler is not
-desired, you should use `GetSignalHandler()` of **`TApplication`** to
-get the interrupt handler and to remove it by `RemoveSignalHandler()`of
-**`TSystem`** .
-
-## Glossary
-
-
-The following glossary is adapted from the description of the Rogue Wave
-`Threads.h`++ package.
-
-A **`process`** is a program that is loaded into memory and prepared for
-execution. Each process has a private address space. Processes begin
-with a single thread.
-
-A **`thread`** is a sequence of instructions being executed in a
-program. A thread has a program counter and a private stack to keep
-track of local variables and return addresses. A multithreaded process
-is associated with one or more threads. Threads execute independently.
-All threads in a given process share the private address space of that
-process.
-
-**`Concurrency`** exists when at least two threads are in progress at
-the same time. A system with only a single processor can support
-concurrency by switching execution contexts among multiple threads.
-
-**`Parallelism`** arises when at least two threads are executing
-simultaneously. This requires a system with multiple processors.
-Parallelism implies concurrency, but not vice-versa.
-
-A function is **`reentrant`** if it will behave correctly even if a
-thread of execution enters the function while one or more threads are
-already executing within the function. These could be the same thread,
-in the case of recursion, or different threads, in the case of
-concurrency.
-
-**`Thread-specific data`** (**`TSD`**) is also known as thread-local
-storage (TLS). Normally, any data that has lifetime beyond the local
-variables on the thread's private stack are shared among all threads
-within the process. Thread-specific data is a form of static or global
-data that is maintained on a per-thread basis. That is, each thread gets
-its own private copy of the data.
-
-Left to their own devices, threads execute independently.
-**`Synchronization`** is the work that must be done when there are, in
-fact, interdependencies that require some form of communication among
-threads. Synchronization tools include mutexes, semaphores, condition
-variables, and other variations on locking.
-
-A **`critical section`** is a section of code that accesses a
-non-sharable resource. To ensure correct code, only one thread at a time
-may execute in a critical section. In other words, the section is not
-reentrant.
-
-A **`mutex`**, or mutual exclusion lock, is a synchronization object
-with two states locked and unlocked. A mutex is usually used to ensure
-that only one thread at a time executes some critical section of code.
-Before entering a critical section, a thread will attempt to lock the
-mutex, which guards that section. If the mutex is already locked, the
-thread will block until the mutex is unlocked, at which time it will
-lock the mutex, execute the critical section, and unlock the mutex upon
-leaving the critical section.
-
-A **`semaphore`** is a synchronization mechanism that starts out
-initialized to some positive value. A thread may ask to wait on a
-semaphore in which case the thread blocks until the value of the
-semaphore is positive. At that time the semaphore count is decremented
-and the thread continues. When a thread releases semaphore, the
-semaphore count is incremented. Counting semaphores are useful for
-coordinating access to a limited pool of some resource.
-
-**`Readers/Writer Lock`** - a multiple-reader, single-writer lock is one
-that allows simultaneous read access by many threads while restricting
-write access to only one thread at a time. When any thread holds the
-lock for reading, other threads can also acquire the lock reading. If
-one thread holds the lock for writing, or is waiting to acquire the lock
-for writing, other threads must wait to acquire the lock for either
-reading or writing.
-
-Use a **`condition variable`** in conjunction with a mutex lock to
-automatically block threads until a particular condition is true.
-
-**`Multithread Safe Levels`** - a possible classification scheme to
-describe thread-safety of libraries:
-
--   All public and protected functions are reentrant. The library
-    provides protection against multiple threads trying to modify static
-    and global data used within a library. The developer must explicitly
-    lock access to objects shared between threads. No other thread can
-    write to a locked object unless it is unlocked. The developer needs
-    to lock local objects. The spirit, if not the letter of this
-    definition, requires the user of the library only to be familiar
-    with the semantic content of the objects in use. Locking access to
-    objects that are being shared due to extra-semantic details of
-    implementation (for example, copy-on-write) should remain the
-    responsibility of the library.
-
--   All public and protected functions are reentrant. The library
-    provides protection against multiple threads trying to modify static
-    and global data used within the library. The preferred way of
-    providing this protection is to use mutex locks. The library also
-    locks an object before writing to it. The developer is not required
-    to explicitly lock or unlock a class object (static, global or
-    local) to perform a single operation on the object. Note that even
-    multithread safe level II hardly relieves the user of the library
-    from the burden of locking.
-
-A thread suffers from **`deadlock`** if it is blocked waiting for a
-condition that will never occur. Typically, this occurs when one thread
-needs to access a resource that is already locked by another thread, and
-that other thread is trying to access a resource that has already been
-locked by the first thread. In this situation, neither thread is able to
-progress; they are deadlocked.
-
-A **`multiprocessor`** is a hardware system with multiple processors or
-multiple, simultaneous execution units.
-
--   Examples can be found at
-    <http://www-linux.gsi.de/~go4/HOWTOthreads/howtothreadsbody.html>
-    (the thread authors' web site - Jörn Adamczewski and Marc
-    Hemberger).
-
diff --git a/documentation/users-guide/Trees.md b/documentation/users-guide/Trees.md
deleted file mode 100644
index 777b252e96484..0000000000000
--- a/documentation/users-guide/Trees.md
+++ /dev/null
@@ -1,4179 +0,0 @@
-# Trees
-
-
-## Why Should You Use a Tree?
-
-
-In the "Input/Output" chapter, we saw how objects can be saved in ROOT
-files. In case you want to store large quantities of same-class objects,
-ROOT has designed the **`TTree`** and **`TNtuple`** classes specifically
-for that purpose. The **`TTree`** class is optimized to reduce disk
-space and enhance access speed. A **`TNtuple`** is a **`TTree`** that is
-limited to only hold floating-point numbers; a **`TTree`** on the other
-hand can hold all kind of data, such as objects or arrays in addition to
-all the simple types.
-
-When using a **`TTree`**, we fill its branch buffers with leaf data and
-the buffers are written to disk when it is full. Branches, buffers, and
-leafs, are explained a little later in this chapter, but for now, it is
-important to realize that each object is not written individually, but
-rather collected and written a bunch at a time.
-
-This is where the **`TTree`** takes advantage of compression and will
-produce a much smaller file than if the objects were written
-individually. Since the unit to be compressed is a buffer, and the
-**`TTree`** contains many same-class objects, the header of the objects
-can be compressed.
-
-The **`TTree`** reduces the header of each object, but it still contains
-the class name. Using compression, the class name of each same-class
-object has a good chance of being compressed, since the compression
-algorithm recognizes the bit pattern representing the class name. Using
-a **`TTree`** and compression the header is reduced to about 4 bytes
-compared to the original 60 bytes. However, if compression is turned
-off, you will not see these large savings.
-
-The **`TTree`** is also used to optimize the data access. A tree uses a
-hierarchy of branches, and each branch can be read independently from
-any other branch. Now, assume that `Px` and `Py` are data members of the
-event, and we would like to compute `Px2 + Py2` for every event
-and histogram the result.
-
-If we had saved the million events without a **`TTree`** we would have
-to:
-
--   read each event in its entirety into memory
--   extract the `Px` and `Py` from the event
--   compute the sum of the squares
--   fill a histogram
-
-We would have to do that a million times! This is very time consuming,
-and we really do not need to read the entire event, every time. All we
-need are two little data members (`Px` and `Py`). On the other hand, if
-we use a tree with one branch containing `Px` and another branch
-containing `Py`, we can read all values of `Px` and `Py` by only reading
-the `Px` and `Py` branches. This makes the use of the **`TTree`** very
-attractive.
-
-## A Simple TTree
-
-
-This script builds a **`TTree`** from an ASCII file containing
-statistics about the staff at CERN. This script, `tree500_cernbuild.C` and its input
-file `cernstaff.dat` are in `$ROOTSYS/tutorials/io/tree`.
-
-``` {.cpp}
-{
-   // Simplified version of cernbuild.C.
-   // This macro to read data from an ascii file and
-   // create a root file with a TTree
-
-   Int_t           Category;
-   UInt_t          Flag;
-   Int_t           Age;
-   Int_t           Service;
-   Int_t           Children;
-   Int_t           Grade;
-   Int_t           Step;
-   Int_t           Hrweek;
-   Int_t           Cost;
-   Char_t          Division[4];
-   Char_t          Nation[3];
-
-   FILE *fp = fopen("cernstaff.dat","r");
-
-   TFile *hfile = hfile = TFile::Open("cernstaff.root","RECREATE");
-
-   TTree *tree = new TTree("T","CERN 1988 staff data");
-   tree->Branch("Category",&Category,"Category/I");
-   tree->Branch("Flag",&Flag,"Flag/i");
-   tree->Branch("Age",&Age,"Age/I");
-   tree->Branch("Service",&Service,"Service/I");
-   tree->Branch("Children",&Children,"Children/I");
-   tree->Branch("Grade",&Grade,"Grade/I");
-   tree->Branch("Step",&Step,"Step/I");
-   tree->Branch("Hrweek",&Hrweek,"Hrweek/I");
-   tree->Branch("Cost",&Cost,"Cost/I");
-   tree->Branch("Division",Division,"Division/C");
-   tree->Branch("Nation",Nation,"Nation/C");
-   char line[80];
-   while (fgets(line,80,fp)) {
-      sscanf(&line[0],"%d %d %d %d %d %d %d  %d %d %s %s",
-      &Category,&Flag,&Age,&Service,&Children,&Grade,&Step,&Hrweek,&Cost,Division,Nation);
-      tree->Fill();
-   }
-   tree->Print();
-   tree->Write();
-
-   fclose(fp);
-   delete hfile;
-}
-```
-
-The script opens the
-ASCII file, creates a ROOT file and a **`TTree`**. Then it creates
-branches with the `TTree::Branch` method. The first parameter of the
-`Branch` method is the branch name. The second parameter is the address
-from which the first leaf is to be read. Once the branches are defined, the script
-reads the data from the ASCII file into C variables and
-fills the `tree`. The ASCII file is closed, and the ROOT file is written
-to disk saving the `tree`. Remember, trees (and histograms) are created in
-the current directory, which is the file in our example. Hence a
-`f->Write() `saves the tree.
-
-## Show an Entry with TTree::Show
-
-
-An easy way to access one entry of a tree is the use the `TTree::Show`
-method. For example to look at the 10th entry in the `cernstaff.root` tree:
-
-``` {.cpp}
-root[] TFile f("cernstaff.root")
-root[] T->Show(10)
-======> EVENT:10
- Category        = 361
- Flag            = 15
- Age             = 51
- Service         = 29
- Children        = 0
- Grade           = 7
- Step            = 13
- Hrweek          = 40
- Cost            = 7599
- Division        = PS
- Nation          = FR
-```
-
-## Print the Tree Structure with TTree::Print
-
-
-A helpful command to see the tree structure meaning the number of
-entries, the branches and the leaves, is `TTree::Print`.
-
-``` {.cpp}
-root[] T->Print()
-**********************************************************************
-*Tree    :T         : staff data from ascii file                     *
-*Entries :3354      : Total = 245417 bytes  File  Size =        59945*
-*                     Tree compression factor =   2.90               *
-**********************************************************************
-*Br    0 :staff     :Category/I:Flag:Age:Service:Children:Grade:...  *
-*         | Cost                                                     *
-*Entries :3354 : Total Size  = 154237 bytes  File Size = 32316       *
-*Baskets :   3 : Basket Size =  32000 bytes  Compression= 2.97       *
-```
-
-## Scan a Variable the Tree with TTree::Scan
-
-
-The `TTree::Scan` method shows all values of the list of leaves
-separated by a colon.
-
-``` {.cpp}
-root[] T->Scan("Cost:Age:Children")
-************************************************
-*    Row   *      Cost *       Age *  Children *
-************************************************
-*        0 *     11975 *        58 *         0 *
-*        1 *     10228 *        63 *         0 *
-*        2 *     10730 *        56 *         2 *
-*        3 *      9311 *        61 *         0 *
-*        4 *      9966 *        52 *         2 *
-*        5 *      7599 *        60 *         0 *
-*        6 *      9868 *        53 *         1 *
-*        7 *      8012 *        60 *         1 *
-...
-```
-
-## The Tree Viewer
-
-![Activating the tree viewer](pictures/030000EF.png)
-
-The tree viewer is a quick and easy way to examine a tree. To start the
-tree viewer, open a file and object browser. Right click on a
-**`TTree`** and select `StartViewer`. You can also start the tree viewer
-from the command line. First load the viewer library.
-
-
-``` {.cpp}
-root[] TFile f("cernstaff.root")
-root[] T->StartViewer()
-```
-
-If you want to start a tree viewer without a tree, you need to load the
-tree player library first:
-
-``` {.cpp}
-root[] gSystem->Load("libTreeViewer.so")
-root[] new TTreeViewer()
-```
-
-The figure above shows how the tree viewer looks like for the example file
-`cernstaff.root`. The left panel contains the list of trees and their
-branches; in this case there is only one tree. You can add more trees
-with the File-Open command to open the file containing the new tree,
-then use the context menu on the right panel, select `SetTreeName` and
-enter the name of the tree to add. On the right are the leaves or
-variables in the tree. You can double click on any leaf to a histogram
-it.
-
-The toolbar in the upper part can be used for user commands, changing
-the drawing option and the histogram name. The lower part contains three
-picture buttons that draw a histogram, stop the current command, and
-refresh the tree.
-
-
-The three check buttons toggle the following:
-
-`Hist`- the histogram drawing mode;
-
-`Scan`- enables redirecting of `TTree::Scan `command in an ASCII file;
-
-`Rec` - enables recording of the last issued command.
-
-- ![](pictures/020000F1.jpg) To draw more than one dimension you can drag
-and drop any leaf to the `X,Y,Z` boxes". Then push the Draw button,
-witch is marked with the purple icon on the bottom left.
-
-- ![](pictures/030000F2.png) All commands can be interrupted at any time
-by pressing this button.
-
-- ![](pictures/030000F3.png) The method **`TTree::Refresh`** is called by
-pressing the refresh button in `TTreeViewer`. It redraws the current
-exposed expression. Calling `TTree::Refresh` is useful when a tree is
-produced by a writer process and concurrently analyzed by one or more
-readers.
-
-- ![](pictures/030000F4.png) To add a cut/weight to the histogram, enter an
-expression in the "cut box". The cut box is the one with the scissor
-icon.
-
-Below them there are two text widgets for specifying the input and
-output event lists. A Tree Viewer session is made by the list of
-user-defined expressions and cuts, applying to a specified tree. A
-session can be saved using File / `SaveSource` menu or the `SaveSource`
-method from the context menu of the right panel. This will create a
-macro having as default name `treeviewer.C` that can be ran at any time
-to reproduce the session.
-
-Besides the list of user-defined expressions, a session may contain a
-list of RECORDS. A record can be produced in the following way: dragging
-leaves/expression on X/Y/Z; changing drawing options; clicking the RED
-button on the bottom when happy with the histogram
-
-NOTE that just double clicking a leaf will not produce a record: the
-histogram must be produced when clicking the DRAW button on the
-bottom-left. The records will appear on the list of records in the
-bottom right of the tree viewer. Selecting a record will draw the
-corresponding histogram. Records can be played using the arrow buttons
-near to the record button. When saving the session, the list of records
-is being saved as well.
-
-Records have a default name corresponding to the Z: Y: X selection, but
-this can be changed using `SetRecordName()` method from the right panel
-context menu. You can create a new expression by right clicking on any
-of the` E()` boxes. The expression can be dragged and dropped into any
-of the boxes (`X,` `Y,` `Z,` `Cut`, or `Scan`). To scan one or more
-variables, drop them into the Scan box, then double click on the box.
-You can also redirect the result of the scan to a file by checking the
-Scan box on top.
-
-![](pictures/030000F5.png)
-
-When the "`Rec`" box is checked, the `Draw` and `Scan` commands are
-recorded in the history file and echoed on the command line. The
-"Histogram" text box contains the name of the resulting histogram. By
-default it is `htemp`. You can type any name, if the histogram does not
-exist it will create one. The Option text box contains the list of Draw
-options. See "Draw Options". You can select the options with the Options
-menu. The Command box lets you enter any command that you could also
-enter on the command line. The vertical slider on the far left side can
-be used to select the minimum and maximum of an event range. The actual
-start and end index are shown in on the bottom in the status window.
-
-There is an extensive help utility accessible with the Help menu. The
-`IList` and `OList` are to `specify` an input list of entry indices and
-a name for the output list respectively. Both need to be of type
-**`TList`** and contain integers of entry indices. These lists are
-described below in the paragraph "**Error! Reference source not
-found.**".
-
-![A couple of graphs](pictures/030000F6.png)
-
-The first one is a plot of the age distribution, the second a scatter
-plot of the cost vs. age. The second one was generated by dragging the
-age leaf into the Y-box and the cost leaf into the X-box, and pressing
-the Draw button. By default, this will generate a scatter plot. Select a
-different option, for example `"lego"` to create a 2D histogram.
-
-## Creating and Saving Trees
-
-
-This picture shows the **`TTree`** class:
-
-![The TTree class](pictures/030000F8.png)
-
-To create a **`TTree`** we use its constructor. Then we design our data
-layout and add the branches. A tree can be created by giving a name and
-title:
-
-``` {.cpp}
-   TTree t("MyTree","Example Tree");
-```
-
-### Creating a Tree from a Folder Hierarchy
-
-
-An alternative way to create a tree and organize it is to use folders
-(see "Folders and Tasks"). You can build a folder structure and create a
-tree with branches for each of the sub-folders:
-
-``` {.cpp}
-   TTree folder_tree("MyFolderTree","/MyFolder");
-```
-
-The second argument `"/MyFolder" `is the top folder, and the "/" signals
-the **`TTree`** constructor that this is a folder not just the title.
-You fill the tree by placing the data into the folder structure and
-calling `TTree::Fill`.
-
-### Tree and TRef Objects
-
-
-``` {.cpp}
-   MyTree->BranchRef();
-```
-
-This call requests the construction of an optional branch supporting
-table of references (**`TRefTable`**). This branch (**`TBranchRef`**)
-will keep all the information needed to find the branches containing
-referenced objects at each `Tree::Fill`, the branch numbers containing
-the referenced objects are saved in the table of references. When the
-Tree header is saved (via `TTree::Write` for example), the branch is
-saved, keeping the information with the pointers to the branches having
-referenced objects. Enabling this optional table, allow
-`TTree::Draw` to automatically load the branches needed to
-dereference a **`TRef`** (or **`TRefArray`**) object.
-
-### Autosave
-
-
-`Autosave` gives the option to save all branch buffers every `n` byte.
-We recommend using `Autosave` for large acquisitions. If the acquisition
-fails to complete, you can recover the file and all the contents since
-the last `Autosave`. To set the number of bytes between `Autosave` you
-can use the `TTree::SetAutosave()` method. You can also call
-**`TTree::Autosave` in the acquisition loop every `n `entry.**
-
-### Trees with Circular Buffers
-
-
-When a **`TTree`** is memory resident, you set it up so that it retains
-retain only the last few entries. For example, this can be very useful
-for monitoring purpose.
-
-``` {.cpp}
-   void TTree::SetCircular(Long64_t maxEntries);
-```
-
-where `maxEntries` is the maximum number of entries to be kept in the
-buffers. When the number of entries exceeds this value, the first
-entries in the **`Tree`** are deleted and the buffers used again. An
-example of a script using a circular buffer is shown below:
-
-``` {.cpp}
-void circular() {
-   gROOT->cd(); //make sure that the Tree is memory resident
-   TTree *T = new TTree("T","test circular buffers");
-   TRandom r;
-   Float_t px,py,pz;
-   Double_t random;
-   UShort_t i;
-   T->Branch("px",&px,"px/F");
-   T->Branch("py",&py,"py/F");
-   T->Branch("pz",&pz,"pz/F");
-   T->Branch("random",&random,"random/D");
-   T->Branch("i",&i,"i/s");
-   T->SetCircular(20000);
-   for (i = 0; i < 65000; i++) {
-      r.Rannor(px,py);
-      pz = px*px + py*py;
-      random = r.Rndm();
-      T->Fill();
-   }
-   T->Print();
-}
-```
-
-### Size of TTree in the File
-
-
-When writing a **`TTree`** to a file, if the file size reaches the value
-stored in the `TTree::GetMaxTreeSize()`, the current file is closed and
-a new file is created. If the original file is named "`myfile.root`",
-subsequent files are named "`myfile_1.root`", "`myfile_2.root`", etc.
-
-Currently, the automatic change of file is restricted to the case where
-the tree is in the top level directory. The file should not contain
-sub-directories. Before switching to a new file, the tree header is
-written to the current file, then the current file is closed. To process
-the multiple files created by `ChangeFile()`, one must use a
-**`TChain`**.
-
-The new file name has a suffix "`_N`" where `N` is equal to
-`fFileNumber+1`. By default a Root session starts with `fFileNumber=0`.
-One can set `fFileNumber` to a different value via
-`TTree::SetFileNumber()`. In case a file named "`_N`" already exists,
-the function will try a file named "`__N`", then "`___N`", etc. The
-maximum tree size can be set via the static function
-`TTree::SetMaxTreeSize()`. The default value of `fgMaxTreeSize` is 100
-GB. If the current file contains other objects (like **`TH1`** and
-**`TTree`**), these objects are automatically moved to the new file.
-
-### User Info Attached to a TTree Object
-
-
-The function `TTree::GetUserInfo()` allows adding any object defined by
-a user to the tree that is not depending on the entry number. For
-example:
-
-``` {.cpp}
-   tree->GetUserInfo()->Add(myruninfo);
-```
-
-### Indexing a Tree
-
-
-Use `TTree::BuildIndex()`, to build an index table using expressions
-depending on the value in the leaves.
-
-``` {.cpp}
-tree->BuildIndex(majorname, minorname);
-```
-
-The index is built in the following way:
-
--   a pass on all entries is made like in `TTree::Draw()`
--   `var1 = majorname`
--   `var2 = minorname`
--   `sel  = ` $2^{31} \times majorname + minorname$
--   for each entry in the tree the sel expression is evaluated and the
-    results array is sorted into `fIndexValues`
-
-Once the index is computed, using the
-`TTree::GetEntryWithIndex(majornumber, minornumber)` one entry can be
-retrieved. Example:
-
-``` {.cpp}
-   // to create an index using leaves Run and Event
-   tree.BuildIndex("Run","Event");
-   // to read entry corresponding to Run=1234 and Event=56789
-   tree.GetEntryWithIndex(1234,56789);
-```
-
-Note that `majorname` and `minorname` may be expressions using original
-tree variables e.g.: "`run-90000`", "`event +3*xx`". In case an
-expression is specified, the equivalent expression must be computed when
-calling `GetEntryWithIndex()`. To build an index with only `majorname`,
-specify `minorname="0"` (default).
-
-Note that once the index is built, it can be saved with the **`TTree`**
-object with:
-
-``` {.cpp}
-   tree.Write();     //if the file has been open in "update" mode
-```
-
-The most convenient place to create the index is at the end of the
-filling process just before saving the tree header. If a previous index
-was computed, it is redefined by this new call.
-
-Note that this function can also be applied to a **`TChain`**. The
-return value is the number of entries in the Index (\< 0 indicates
-failure).
-
-## Branches
-
-
-The organization of branches allows the designer to optimize the data
-for the anticipated use. The class for a branch is called **`TBranch`**.
-If two variables are independent, and the designer knows the variables
-will not be used together, they should be placed on separate branches.
-If, however, the variables are related, such as the coordinates of a
-point, it is most efficient to create one branch with both coordinates
-on it. A variable on a **`TBranch`** is called a leaf (yes -
-**`TLeaf`**). Another point to keep in mind when designing trees is that
-branches of the same **`TTree`** can be written to separate files. To
-add a **`TBranch`** to a **`TTree`** we call the
-method **`TTree::Branch()`**. Note that we DO NOT use the `TBranch`
-constructor.
-
-The `TTree::Branch` method has several signatures. The branch type
-differs by what is stored in it. A branch can hold an entire object, a
-list of simple variables, contents of a folder, contents of a
-**`TList`**, or an array of objects. Let's see some examples. To follow
-along you will need the shared library `libEvent.so`. First, check if it
-is in `$ROOTSYS/test`. If it is, copy it to your own area. If it is not
-there, you have to build it by typing make in `$ROOTSYS/test`.
-
-## Adding a Branch to Hold a List of Variables
-
-
-As in the very first example (`cernstaff.root.root`)
-the data we want to save is a list of simple variables, such as integers
-or floats. In this case, we use the following `TTree::Branch` signature:
-
-``` {.cpp}
-   tree->Branch("Ev_Branch",&event,
-                "temp/F:ntrack/I:nseg:nvtex:flag/i");
-```
-
-The first parameter is the branch name.
-
-The second parameter is the address from which the first variable is to
-be read. In the code above, "event" is a structure with one float and
-three integers and one unsigned integer. You should not assume that the
-compiler aligns the elements of a structure without gaps. To avoid
-alignment problems, you need to use structures with same length members.
-If your structure does not qualify, you need to create one branch for
-each element of the structure.
-
-The leaf name is NOT used to pick the variable out of the structure, but
-is only used as the name for the leaf. This means that the list of
-variables needs to be in a structure in the order described in the third
-parameter.
-
-This third parameter is a string describing the leaf list. Each leaf has
-a name and a type separated by a "/" and it is separated from the next
-leaf by a "`:`".
-
-``` {.cpp}
-<Variable>/<type>:<Variable>/<type>
-```
-
-The example on the next line has two leafs: a floating-point number
-called temp and an integer named `ntrack`.
-
-``` {.cpp}
-"temp/F:ntrack/I:"
-```
-
-The type can be omitted and if no type is given, the same type as the
-previous variable is assumed. This leaf list has three integers called
-`ntrack`, `nseg`, and `nvtex`.
-
-``` {.cpp}
-"ntrack/I:nseg:nvtex"
-```
-
-There is one more rule: when no type is given for the very first leaf,
-it becomes a `float` (F). This leaf list has three floats called `temp`,
-`mass`, and `px`.
-
-``` {.cpp}
-"temp:mass:px"
-```
-
-The symbols used for the type are:
-
--   `C`: a character string terminated by the 0 character
--   `B`: an 8 bit signed integer
--   `b`: an 8 bit unsigned integer
--   `S`: a 16 bit signed integer
--   `s`: a 16 bit unsigned integer
--   `I`: a 32 bit signed integer
--   `i`: a 32 bit unsigned integer
--   `L`: a 64 bit signed integer
--   `l`: a 64 bit unsigned integer
--   `G`: a long signed integer, stored as 64 bit
--   `g`: a long unsigned integer, stored as 64 bit
--   `F`: a 32 bit floating point
--   `D`: a 64 bit floating point
--   `O`: [the letter 'o', not a zero] a boolean (Bool\_t)
-
-The type is used for a byte count to decide how much space to allocate.
-The variable written is simply the block of bytes starting at the
-starting address given in the second parameter. It may or may not match
-the leaf list depending on whether or not the programmer is being
-careful when choosing the leaf address, name, and type.
-
-By default, a variable will be copied with the number of bytes specified
-in the type descriptor symbol. However, if the type consists of two
-characters, the number specifies the number of bytes to be used when
-copying the variable to the output buffer. The line below describes
-`ntrack` to be written as a 16-bit integer (rather than a 32-bit
-integer).
-
-``` {.cpp}
-"ntrack/I2"
-```
-
-With this Branch method, you can also add a leaf that holds an entire
-array of variables. To add an array of floats use the `f[n]` notation
-when describing the leaf.
-
-``` {.cpp}
-   Float_t  f[10];
-   tree->Branch("fBranch",f,"f[10]/F");
-```
-
-You can also add an array of variable length:
-
-``` {.cpp}
-{
-   TFile *f = new TFile("peter.root","recreate");
-   Int_t nPhot;
-   Float_t E[500];
-   TTree* nEmcPhotons = new TTree("nEmcPhotons","EMC Photons");
-   nEmcPhotons->Branch("nPhot",&nPhot,"nPhot/I");
-   nEmcPhotons->Branch("E",E,"E[nPhot]/F");
-}
-```
-
-See "Example 2: A Tree with a C Structure" below
-(`$ROOTSYS/tutorials/io/tree/tree105_tree.C`) and `tree502_staff.C` at the beginning of
-this chapter.
-
-## Adding a TBranch to Hold an Object
-
-
-To write a branch to hold an event object, we need to load the
-definition of the `Event` class, which is in `$ROOTSYS/test/libEvent.so`
-(if it doesn't exist type make in `$ROOTSYS/test`). An object can be
-saved in a tree if a ROOT dictionary for its class has been generated
-and loaded.
-
-``` {.cpp}
-root[] .L libEvent.so
-```
-
-First, we need to open a file and create a tree.
-
-``` {.cpp}
-root[]     TFile *f = new TFile("AFile.root","RECREATE")
-root[]     TTree *tree = new TTree("T","A Root Tree")
-```
-
-We need to create a pointer to an `Event` object that will be used as a
-reference in the `TTree::Branch` method. Then we create a branch
-with the `TTree::Branch` method.
-
-``` {.cpp}
-root[]     Event *event = new Event()
-root[]     tree->Branch("EventBranch","Event",&event,32000,99)
-```
-
-To add a branch to hold an object we use the signature above. The first
-parameter is the name of the branch. The second parameter is the name of
-the class of the object to be stored. The third parameter is the address
-of a pointer to the object to be stored.
-
-Note that it is an address of a pointer to the object, not just a
-pointer to the object.
-
-The fourth parameter is the buffer size and is by default 32000 bytes.
-It is the number of bytes of data for that branch to save to a buffer
-until it is saved to the file. The last parameter is the split-level,
-which is the topic of the next section. Static class members are not
-part of an object and thus not written with the object. You could store
-them separately by collecting these values in a special "status" object
-and write it to the file outside of the tree. If it makes sense to store
-them for each object, make them a regular data member.
-
-### Setting the Split-level
-
-
-To split a branch means to create a sub-branch for each data member in
-the object. The split-level can be set to 0 to disable splitting or it
-can be set to a number between 1 and 99 indicating the depth of
-splitting.
-
-If the split-level is set to zero, the whole object is written in its
-entirety to one branch. The **`TTree`** will look like the one on the
-right, with one branch and one leaf holding the entire event object.
-
-![A split and not split tree](pictures/030000FA.png)
-
-When the split-level is 1, an object data member is assigned a branch.
-If the split-level is 2, the data member objects will be split also, and
-a split level of 3 its data members objects, will be split. As the
-split-level increases so does the splitting depth. The ROOT default for
-the split-level is 99. This means the object will be split to the
-maximum.
-
-#### Memory Considerations when Splitting a Branch
-
-Splitting a branch can quickly generate many branches. Each branch has
-its own buffer in memory. In case of many branches (say more than 100),
-you should adjust the buffer size accordingly. A recommended buffer size
-is 32000 bytes if you have less than 50 branches. Around 16000 bytes if
-you have less than 100 branches and 4000 bytes if you have more than 500
-branches. These numbers are recommended for computers with memory size
-ranging from 32MB to 256MB. If you have more memory, you should specify
-larger buffer sizes. However, in this case, do not forget that your file
-might be used on another machine with a smaller memory configuration.
-
-#### Performance Considerations when Splitting a Branch
-
-A split branch is faster to read, but slightly slower to write. The
-reading is quicker because variables of the same type are stored
-consecutively and the type does not have to be read each time. It is
-slower to write because of the large number of buffers as described
-above. See "
-
-Performance Benchmarks" for performance impact of split and non-split
-mode.
-
-#### Rules for Splitting
-
-When splitting a branch, variables of different types are handled
-differently. Here are the rules that apply when splitting a branch.
-
--   If a data member is a basic type, it becomes one branch of class
-    **`TBranchElement`**.
-
--   A data member can be an array of basic types. In this case, one
-    single branch is created for the array.
-
--   A data member can be a pointer to an array of basic types. The
-    length can vary, and must be specified in the comment field of the
-    data member in the class definition. See "Input/Output".
-
--   Pointer data member are not split, except for pointers to a
-    **`TClonesArray`**. The **`TClonesArray`** (pointed to) is split if
-    the split level is greater than two. When the split level is one,
-    the **`TClonesArray`** is not split.
-
--   If a data member is a pointer to an object, a special branch is
-    created. The branch will be filled by calling the class `Streamer`
-    function to serialize the object into the branch buffer.
-
--   If a data member is an object, the data members of this object are
-    split into branches according to the split-level (i.e. split-level
-    \> 2).
-
--   Base classes are split when the object is split.
-
--   Abstract base classes are never split.
-
--   All STL containers are supported.
-
-``` {.cpp}
-   // STL vector of vectors of TAxis*
-   vector<vector<TAxis *> >  fVectAxis;
-   // STL map of string/vector
-   map<string,vector<int> >  fMapString;
-   // STL deque of pair
-   deque<pair<float,float> > fDequePair;
-```
-
--   C-structure data members are not supported in split mode.
-
--   An object that is not split may be slow to browse.
-
--   A STL container that is not split will not be accessible in the
-    browser.
-
-### Exempt a Data Member from Splitting
-
-
-If you are creating a branch with an object and in general you want the
-data members to be split, but you want to exempt a data member from the
-split. You can specify this in the comment field of the data member:
-
-``` {.cpp}
-class Event : public TObject {
-   private:
-      EventHeader    fEvtHdr;      //|| Don't split the header
-```
-
-### Adding a Branch to Hold a TClonesArray
-
-
-ROOT has two classes to manage arrays of objects. The **`TObjArray`**
-can manage objects of different classes, and the **`TClonesArray`** that
-specializes in managing objects of the same class (hence the name Clones
-Array). **`TClonesArray`** takes advantage of the constant size of each
-element when adding the elements to the array. Instead of allocating
-memory for each new object as it is added, it reuses the memory. Here is
-an example of the time a **`TClonesArray`** can save over a
-**`TObjArray`**. We have 100,000 events, and each has 10,000 tracks,
-which gives 1,000,000,000 tracks. If we use a **`TObjArray`** for the
-tracks, we implicitly make a call to new and a corresponding call to
-delete for each track. The time it takes to make a pair of new/delete
-calls is about 7 s (10-6). If we multiply the number of tracks by 7 s,
-(1,000,000,000 \* 7 \* 10-6) we calculate that the time allocating and
-freeing memory is about 2 hours. This is the chunk of time saved when a
-**`TClonesArray`** is used rather than a **`TObjArray`**. If you do not
-want to wait 2 hours for your tracks (or equivalent objects), be sure to
-use a **`TClonesArray`** for same-class objects arrays. Branches with
-**`TClonesArrays`** use the same method (`TTree::Branch`) as any other
-object described above. If splitting is specified the objects in the
-**`TClonesArray`** are split, not the **`TClonesArray`** itself.
-
-### Identical Branch Names
-
-
-When a top-level object (say `event`), has two data members of the same
-class the sub branches end up with identical names. To distinguish the
-sub branch we must associate them with the master branch by including a
-"`.`" (a dot) at the end of the master branch name. This will force the
-name of the sub branch to be `master.sub` branch instead of simply `sub`
-branch. For example, a tree has two branches `Trigger` and
-`MuonTrigger`, each containing an object of the same class (`Trigger`).
-To identify uniquely the sub branches we add the dot:
-
-``` {.cpp}
-   tree->Branch("Trigger.","Trigger",&b1,8000,1);
-   tree->Branch("MuonTrigger.","Trigger",&b2,8000,1);
-```
-
-If `Trigger` has three members, `T1`, `T2`, `T3`, the two instructions
-above will generate sub branches called: `Trigger.T1`, `Trigger.T2`,
-`Trigger.T3`, `MuonTrigger.T1`, `MuonTrigger.T2`, and` MuonTrigger.T3`.
-
-## Adding a Branch with a Folder
-
-
-Use the syntax below to add a branch from a folder:
-
-``` {.cpp}
-   tree->Branch("/aFolder");
-```
-
-This method creates one branch for each element in the folder. The
-method returns the total number of branches created.
-
-## Adding a Branch with a Collection
-
-
-This `Branch` method creates one branch for each element in the
-collection.
-
-``` {.cpp}
-   tree->Branch(*aCollection, 8000, 99);
-   // Int_t TTree::Branch(TCollection *list, Int_t bufsize,
-   //                     Int_t splitlevel, const char *name)
-```
-
-The method returns the total number of branches created. Each entry in
-the collection becomes a top level branch if the corresponding class is
-not a collection. If it is a collection, the entry in the collection
-becomes in turn top level branches, etc. The split level is decreased by
-1 every time a new collection is found. For example if `list` is a
-**`TObjArray`**\*
-
--   If `splitlevel = 1`, one top level branch is created for each
-    element of the **`TObjArray`**.
-
--   If `splitlevel = 2`, one top level branch is created for each array
-    element. If one of the array elements is a **`TCollection`**, one
-    top level branch will be created for each element of this
-    collection.
-
-In case a collection element is a **`TClonesArray`**, the special Tree
-constructor for **`TClonesArray`** is called. The collection itself
-cannot be a **`TClonesArray`**. If `name` is given, all branch names
-will be prefixed with `name_`.
-
-*IMPORTANT NOTE1:* This function should not be called if `splitlevel<1`.
-*IMPORTANT NOTE2:* The branches created by this function will have names
-corresponding to the collection or object names. It is important to give
-names to collections to avoid misleading branch names or identical
-branch names. By default collections have a name equal to the
-corresponding class name, e.g. the default name of **`TList`** is
-"`TList`".
-
-## Examples for Writing and Reading Trees
-
-
-The following sections are examples of writing and reading trees
-increasing in complexity from a simple tree with a few variables to a
-tree containing folders and complex Event objects. Each example has a
-named script in the `$ROOTSYS/tutorials/io/tree` directory. They are called
-tree1.C to tree4.C. The examples are:
-
--   `tree104_tree.C`: a tree with several simple (integers and floating point)
-    variables.
-
--   `tree105_tree.C`: a tree built from a C structure (`struct`). This example
-    uses the `Geant3` C wrapper as an example of a FORTRAN common block
-    ported to C with a C structure.
-
--   `tree107_tree.C:` in this example, we will show how to extend a tree with a
-    branch from another tree with the Friends feature. These trees have
-    branches with variable length arrays. Each entry has a variable
-    number of tracks, and each track has several variables.
-
--   `tree108_tree.C:` a tree with a class (`Event`). The class Event is defined
-    in `$ROOTSYS/test`. In this example we first encounter the impact of
-    splitting a branch.
-
-Each script contains the main function, with the same name as the file
-(i.e. `tree104_tree`), the function to write - `tree104_write`, and the function to
-read - `tree104_read`. If the script is not run in batch mode, it displays the
-tree in the browser and tree viewer. To study the example scripts, you
-can either execute the main script, or load the script and execute a
-specific function. For example:
-
-``` {.cpp}
-// execute the function that writes, reads, shows the tree
-root[]     x tree104_tree.C
-// use ACLiC to build shared library, check syntax, execute
-root[] x tree104_tree.C++
-// Load the script and select a function to execute
-root[]     L tree104_tree.C
-root[]     tree104_write()
-root[]     tree104_read()
-```
-
-## Example 1: A Tree with Simple Variables
-
-
-This example shows how to write, view, and read a tree with several
-simple (integers and floating-point) variables.
-
-### Writing the Tree
-
-
-Below is the function that writes the tree (`tree1w`). First, the
-variables are defined (`px, py, pz,` `random` and `ev`). Then we add a
-branch for each of the variables to the tree, by calling the
-`TTree::Branch` method for each variable.
-
-``` {.cpp}
-void tree104_write(){
-
-   // create a tree file tree1.root - create the file, the Tree and
-   // a few branches
-   TFile f("tree104.root","recreate");
-   TTree t1("t1","a simple Tree with simple variables");
-   Float_t px, py, pz;
-   Double_t random;
-   Int_t ev;
-   t1.Branch("px",&px,"px/F");
-   t1.Branch("py",&py,"py/F");
-   t1.Branch("pz",&pz,"pz/F");
-   t1.Branch("ev",&ev,"ev/I");
-
-   // fill the tree
-   for (Int_t i=0; i<10000; i++) {
-      gRandom->Rannor(px,py);
-      pz = px*px + py*py;
-      random = gRandom->Rndm();
-      ev = i;
-      t1.Fill();
-   }
-   // save the Tree heade; the file will be automatically closed
-   // when going out of the function scope
-   t1.Write();
-}
-```
-
-#### Creating Branches with A single Variable
-
-This is the signature of `TTree::Branch` to create a branch with a list
-of variables:
-
-``` {.cpp}
-   TBranch* TTree::Branch(const char* name,void* address,
-                          const char* leaflist,
-                          Int_t bufsize = 32000)
-```
-
-The first parameter is the branch name. The second parameter is the
-address from which to read the value. The third parameter is the leaf
-list with the name and type of each leaf. In this example, each branch
-has only one leaf. In the box below, the branch is named `px` and has
-one floating point type leaf also called `px`.
-
-``` {.cpp}
-   t1.Branch("px",&px,"px/F");
-```
-
-#### Filling the Tree
-
-First we find some random values for the variables. We assign `px` and
-`py` a Gaussian with mean = 0 and sigma = 1 by calling
-`gRandom->Rannor(px,py)`, and calculate` pz`. Then we call the
-`TTree::Fill()` method. The call `t1.Fill()` fills all branches in the
-tree because we have already organized the tree into branches and told
-each branch where to get the value from. After this script is executed
-we have a ROOT file called `tree104.root` with a tree called `t1`. There
-is a possibility to fill branches one by one using the method
-`TBranch::Fill()`. In this case you do not need to call `TTree::Fill()`
-method. The entries can be set by `TTree::SetEntries(Double_t n)`.
-Calling this method makes sense only if the number of existing entries
-is null.
-
-### Viewing the Tree
-
-
-![The tree104.root file and its tree in the browser and a leaf histogram](pictures/030000FC.png)
-
-In the right panel of the ROOT object browse are the branches: `ev`,
-`px`, `py`, `pz`, and `random`. Note that these are shown as leaves
-because they are "end" branches with only one leaf. To histogram a leaf,
-we can simply double click on it in the browser. This is how the tree
-`t1` looks in the Tree Viewer. Here we can add a cut and add other
-operations for histogramming the leaves. See "The Tree Viewer". For
-example, we can plot a two dimensional histogram.
-
-![The tree viewer](pictures/030000FE.png)
-
-### Reading the Tree
-
-
-The `tree104_read` function shows how to read the tree and access each entry
-and each leaf. We first define the variables to hold the read values.
-
-``` {.cpp}
-   Float_t px, py, pz;
-```
-
-Then we tell the tree to populate these variables when reading an entry.
-We do this with the method `TTree::SetBranchAddress`. The first
-parameter is the branch name, and the second is the address of the
-variable where the branch data is to be placed. In this example, the
-branch name is `px`. This name was given when the tree was written (see
-`tree104_write`). The second parameter is the address of the variable `px`.
-
-``` {.cpp}
-   t1->SetBranchAddress("px",&px);
-```
-
-#### GetEntry
-
-Once the branches have been given the address, a specific entry can be
-read into the variables with the method `TTree::GetEntry(n)`. It
-reads all the branches for entry (n) and populates the given address
-accordingly. By default, `GetEntry()` reuses the space allocated by the
-previous object for each branch. You can force the previous object to be
-automatically deleted if you call `mybranch.SetAutoDelete(kTRUE)`
-(default is `kFALSE`).
-
-Consider the example in `$ROOTSYS/test/Event.h`. The top-level branch in
-the tree `T` is declared with:
-
-``` {.cpp}
-   Event *event = 0;
-   // event must be null or point to a valid object;
-   // it must be initialized
-   T.SetBranchAddress("event",&event);
-```
-
-When reading the Tree, one can choose one of these 3 options:
-
-Option 1:
-
-``` {.cpp}
-   for (Int_t i = 0; i<nentries; i++) {
-      T.GetEntry(i);
-      //the object event has been filled at this point
-   }
-```
-
-This is the default and recommended way to create an object of the class
-`Event. `It will be pointed by `event`.
-
-At the following entries, `event` will be overwritten by the new data.
-All internal members that are **`TObject`**\* are automatically deleted.
-It is important that these members be in a valid state when `GetEntry`
-is called. Pointers must be correctly initialized. However these
-internal members will not be deleted if the characters "`->`" are
-specified as the first characters in the comment field of the data
-member declaration.
-
-The pointer member is read via the `pointer->Streamer(buf)` if "`->`" is
-specified. In this case, it is assumed that the pointer is never null
-(see pointer `TClonesArray *fTracks` in the `$ROOTSYS/test/Event`
-example). If "`->`" is not specified, the pointer member is read via
-`buf >> pointer`. In this case the pointer may be null. Note that the
-option with "`->`" is faster to read or write and it also consumes less
-space in the file.
-
-Option 2 - the option `AutoDelete` is set:
-
-``` {.cpp}
-   TBranch *branch = T.GetBranch("event");
-   branch->SetAddress(&event);
-   branch->SetAutoDelete(kTRUE);
-   for (Int_t i=0; i<nentries; i++) {
-      T.GetEntry(i); // the object event has been filled at this point
-   }
-```
-
-At any iteration, the `GetEntry` deletes the object `event` and a new
-instance of `Event` is created and filled.
-
-Option 3 - same as option 1, but you delete the event yourself:
-
-``` {.cpp}
-   for (Int_t i=0; i<nentries; i++) {
-      delete event;
-      event = 0;      //EXTREMELY IMPORTANT
-      T.GetEntry(i);
-      // the objrect event has been filled at this point
-   }
-```
-
-It is strongly recommended to use the default option 1. It has the
-additional advantage that functions like `TTree::Draw` (internally
-calling `TTree::GetEntry`) will be functional even when the classes in
-the file are not available. Reading selected branches is quicker than
-reading an entire entry. If you are interested in only one branch, you
-can use the `TBranch::GetEntry` method and only that branch is read.
-Here is the script `tree104_read`:
-
-``` {.cpp}
-void tree104_read(){
-   // read the Tree generated by tree1w and fill two histograms
-   // note that we use "new" to create the TFile and TTree objects,
-   // to keep them alive after leaving this function.
-   TFile *f = new TFile("tree104.root");
-   TTree *t1 = (TTree*)f->Get("t1");
-   Float_t px, py, pz;
-   Double_t random;
-   Int_t ev;
-   t1->SetBranchAddress("px",&px);
-   t1->SetBranchAddress("py",&py);
-   t1->SetBranchAddress("pz",&pz);
-   t1->SetBranchAddress("random",&random);
-   t1->SetBranchAddress("ev",&ev);
-   // create two histograms
-   TH1F *hpx   = new TH1F("hpx","px distribution",100,-3,3);
-   TH2F *hpxpy = new TH2F("hpxpy","py vs px",30,-3,3,30,-3,3);
-   //read all entries and fill the histograms
-   Int_t nentries = (Int_t)t1->GetEntries();
-   for (Int_t i=0; i<nentries; i++) {
-      t1->GetEntry(i);
-      hpx->Fill(px);
-      hpxpy->Fill(px,py);
-   }
-   // We do not close the file. We want to keep the generated
-   // histograms we open a browser and the TreeViewer
-   if (gROOT->IsBatch()) return;
-   new TBrowser ();
-   t1->StartViewer();
-
-   //In the browser, click on "ROOT Files", then on "tree1.root"
-   //You can click on the histogram icons in the right panel to draw
-   //them in the TreeViewer, follow the instructions in the Help.
-}
-```
-
-## Example 2: A Tree with a C Structure
-
-
-The executable script for this example is
-`$ROOTSYS/tutorials/io/tree/tree105_tree.C. `In this example we show:
-
--   how to build branches from a C structure
--   how to make a branch with a fixed length array
--   how to make a branch with a variable length array
--   how to read selective branches
--   how to fill a histogram from a branch
--   how to use `TTree::Draw` to show a 3D plot
-
-A C structure (`struct`) is used to build a ROOT tree. In general we
-discourage the use of C structures`,` we recommend using a class
-instead. However, we do support them for legacy applications written in
-C or FORTRAN. The example `struct` holds simple variables and arrays. It
-maps to a Geant3 common block `/gctrak/. `This is the definition of the
-common block/structure:
-
-``` {.cpp}
-const Int_t MAXMEC = 30;
-// PARAMETER (MAXMEC=30)
-// COMMON/GCTRAK/VECT(7),GETOT,GEKIN,VOUT(7)
-//     + ,NMEC,LMEC(MAXMEC)
-//     + ,NAMEC(MAXMEC),NSTEP
-//     + ,PID,DESTEP,DESTEL,SAFETY,SLENG
-//     + ,STEP,SNEXT,SFIELD,TOFG,GEKRAT,UPWGHT
-
-typedef struct {
-   Float_t  vect[7];
-   Float_t  getot;
-   Float_t  gekin;
-   Float_t  vout[7];
-   Int_t    nmec;
-   Int_t    lmec[MAXMEC];
-   Int_t    namec[MAXMEC];
-   Int_t    nstep;
-   Int_t    pid;
-   Float_t  destep;
-   Float_t  destel;
-   Float_t  safety;
-   Float_t  sleng;
-   Float_t  step;
-   Float_t  snext;
-   Float_t  sfield;
-   Float_t  tofg;
-   Float_t  gekrat;
-   Float_t  upwght;
-} Gctrak_t;
-```
-
-When using Geant3, the common block is filled by Geant3 routines at each
-step and only the `TTree::Fill` method needs to be called. In this
-example we emulate the Geant3 step routine with the `helixStep`
-function. We also emulate the filling of the particle values. The calls
-to the `Branch` methods are the same as if Geant3 were used.
-
-``` {.cpp}
-void helixStep(Float_t step, Float_t *vect, Float_t *vout)
-{
-   // extrapolate track in constant field
-   Float_t field = 20; // field in kilogauss
-   enum Evect {kX,kY,kZ,kPX,kPY,kPZ,kPP};
-   vout[kPP] = vect[kPP];
-
-   Float_t h4    = field*2.99792e-4;
-   Float_t rho   = -h4/vect[kPP];
-   Float_t tet   = rho*step;
-   Float_t tsint = tet*tet/6;
-   Float_t sintt = 1 - tsint;
-   Float_t sint  = tet*sintt;
-   Float_t cos1t = tet/2;
-   Float_t f1 = step*sintt;
-   Float_t f2 = step*cos1t;
-   Float_t f3 = step*tsint*vect[kPZ];
-   Float_t f4 = -tet*cos1t;
-   Float_t f5 = sint;
-   Float_t f6 = tet*cos1t*vect[kPZ];
-
-   vout[kX]  = vect[kX]  + (f1*vect[kPX] - f2*vect[kPY]);
-   vout[kY]  = vect[kY]  + (f1*vect[kPY] + f2*vect[kPX]);
-   vout[kZ]  = vect[kZ]  + (f1*vect[kPZ] + f3);
-   vout[kPX] = vect[kPX] + (f4*vect[kPX] - f5*vect[kPY]);
-   vout[kPY] = vect[kPY] + (f4*vect[kPY] + f5*vect[kPX]);
-   vout[kPZ] = vect[kPZ] + (f4*vect[kPZ] + f6);
-}
-```
-
-### Writing the Tree
-
-
-``` {.cpp}
-void tree105_write() {
-   // create a Tree file tree105.root
-
-   // create the file, the Tree and a few branches with
-   // a subset of gctrak
-   TFile f("tree105.root","recreate");
-   TTree t2("t2","a Tree with data from a fake Geant3");
-   Gctrak_t gstep;
-
-   // add the branches for a subset of gstep
-   t2.Branch("vect",gstep.vect,"vect[7]/F");
-   t2.Branch("getot",&gstep.getot,"getot/F");
-   t2.Branch("gekin",&gstep.gekin,"gekin/F");
-   t2.Branch("nmec",&gstep.nmec,"nmec/I");
-   t2.Branch("lmec",gstep.lmec,"lmec[nmec]/I");
-   t2.Branch("destep",&gstep.destep,"destep/F");
-   t2.Branch("pid",&gstep.pid,"pid/I");
-
-   //Initialize particle parameters at first point
-   Float_t px,py,pz,p,charge=0;
-   Float_t vout[7];
-   Float_t mass  = 0.137;
-   Bool_t newParticle = kTRUE;
-   gstep.step    = 0.1;
-   gstep.destep  = 0;
-   gstep.nmec    = 0;
-   gstep.pid     = 0;
-
-   //transport particles
-   for (Int_t i=0; i<10000; i++) {
-      //generate a new particle if necessary (Geant3 emulation)
-      if (newParticle) {
-      px = gRandom->Gaus(0,.02);
-      py = gRandom->Gaus(0,.02);
-      pz = gRandom->Gaus(0,.02);
-      p  = TMath::Sqrt(px*px+py*py+pz*pz);
-      charge = 1;
-      if (gRandom->Rndm() < 0.5) charge = -1;
-         gstep.pid    += 1;
-         gstep.vect[0] = 0;
-         gstep.vect[1] = 0;
-         gstep.vect[2] = 0;
-         gstep.vect[3] = px/p;
-         gstep.vect[4] = py/p;
-         gstep.vect[5] = pz/p;
-         gstep.vect[6] = p*charge;
-         gstep.getot   = TMath::Sqrt(p*p + mass*mass);
-         gstep.gekin   = gstep.getot - mass;
-         newParticle   = kFALSE;
-      }
-      // fill the Tree with current step parameters
-      t2.Fill();
-
-
-      //transport particle in magnetic field (Geant3 emulation)
-      helixStep(gstep.step, gstep.vect, vout);
-      //make one step
-      //apply energy loss
-      gstep.destep   = gstep.step*gRandom->Gaus(0.0002,0.00001);
-      gstep.gekin -= gstep.destep;
-      gstep.getot  = gstep.gekin + mass;
-      gstep.vect[6]= charge*TMath::Sqrt(gstep.getot*gstep.getot
-                      - mass*mass);
-      gstep.vect[0] = vout[0];
-      gstep.vect[1] = vout[1];
-      gstep.vect[2] = vout[2];
-      gstep.vect[3] = vout[3];
-      gstep.vect[4] = vout[4];
-      gstep.vect[5] = vout[5];
-      gstep.nmec    = (Int_t)(5*gRandom->Rndm());
-      for (Int_t l=0; l<gstep.nmec; l++) gstep.lmec[l] = l;
-      if  (gstep.gekin < 0.001) newParticle = kTRUE;
-      if  (TMath::Abs(gstep.vect[2]) > 30) newParticle = kTRUE;
-   }
-   //save the Tree header. The file will be automatically
-   // closed when going out of the function scope
-   t2.Write();
-}
-```
-
-#### Adding a Branch with a Fixed Length Array
-
-At first, we create a tree and create branches for a subset of variables
-in the C structure` Gctrak_t`. Then we add several types of branches.
-The first branch reads seven floating-point values beginning at the
-address of `'gstep.vect'`. You do not need to specify `&gstep.vect`,
-because in C and C++ the array variable holds the address of the first
-element.
-
-``` {.cpp}
-   t2.Branch("vect",gstep.vect,"vect[7]/F");
-   t2.Branch("getot",&gstep.getot,"getot/F");
-   t2.Branch("gekin",&gstep.gekin,"gekin/F");
-```
-
-#### Adding a Branch with a Variable Length Array
-
-The next two branches are dependent on each other. The first holds the
-length of the variable length array and the second holds the variable
-length array. The `lmec` branch reads `nmec` number of integers
-beginning at the address `gstep.lmec`.
-
-``` {.cpp}
-   t2.Branch("nmec",&gstep.nmec,"nmec/I");
-   t2.Branch("lmec",gstep.lmec,"lmec[nmec]/I");
-```
-
-The variable `nmec` is a random number and is reset for each entry.
-
-``` {.cpp}
-   gstep.nmec = (Int_t)(5*gRandom->Rndm());
-```
-
-#### Filling the Tree
-
-In this emulation of Geant3, we generate and transport particles in a
-magnetic field and store the particle parameters at each tracking step
-in a ROOT tree.
-
-### Analysis
-
-
-In this analysis, we do not read the entire entry we only read one
-branch. First, we set the address for the branch to the file `dstep`,
-and then we use the `TBranch::GetEntry` method. Then we fill a histogram
-with the `dstep` branch entries, draw it and fit it with a Gaussian. In
-addition, we draw the particle's path using the three values in the
-vector. Here we use the **`TTree::Draw`** method. It automatically creates
-a histogram and plots the 3 expressions (see Trees in Analysis).
-
-![](pictures/030000FF.png)
-
-``` {.cpp}
-void tree105_read() {
-
-   // read the Tree generated by tree105_write and fill one histogram
-   // we are only interested by the destep branch
-
-   // note that we use "new" to create the TFile and TTree objects because we
-   // want to keep these objects alive when we leave this function
-   TFile *f = new TFile("tree105.root");
-   TTree *t2 = (TTree*)f->Get("t2");
-   static Float_t destep;
-   TBranch *b_destep = t2->GetBranch("destep");
-   b_destep->SetAddress(&destep);
-
-   //create one histogram
-   TH1F *hdestep = new TH1F("hdestep","destep in Mev",100,1e-5,3e-5);
-   //read only the destep branch for all entries
-   Int_t nentries = (Int_t)t2->GetEntries();
-   for (Int_t i=0;i<nentries;i++) {
-      b_destep->GetEntry(i);
-      // fill the histogram with the destep entry
-      hdestep->Fill(destep);
-   }
-
-   // we do not close the file; we want to keep the generated histograms;
-   // we fill a 3-d scatter plot with the particle step coordinates
-   TCanvas *c1 = new TCanvas("c1","c1",600,800);
-   c1->SetFillColor(42);
-   c1->Divide(1,2);
-
-   c1->cd(1);
-   hdestep->SetFillColor(45);
-   hdestep->Fit("gaus");
-
-   c1->cd(2);
-   gPad->SetFillColor(37);                       // continued...
-   t2->SetMarkerColor(kRed);
-   t2->Draw("vect[0]:vect[1]:vect[2]");
-   if (gROOT->IsBatch()) return;
-
-   // invoke the x3d viewer
-   gPad->GetViewer3D("x3d");
-}
-```
-
-## Example 3: Adding Friends to Trees
-
-
-In this example, we will show how to extend a tree with a branch from
-another tree with the Friends feature.
-
-### Adding a Branch to an Existing Tree
-
-
-You may want to add a branch to an existing tree. For example, if one
-variable in the tree was computed with a certain algorithm, you may want
-to try another algorithm and compare the results. One solution is to add
-a new branch, fill it, and save the tree. The code below adds a simple
-branch to an existing tree. Note that the `kOverwrite` option in the
-`Write` method overwrites the existing tree. If it is not specified, two
-copies of the tree headers are saved.
-
-``` {.cpp}
-void tree3AddBranch() {
-   TFile f("tree3.root","update");
-   Float_t new_v;
-   TTree *t3 = (TTree*)f->Get("t3");
-   TBranch *newBranch = t3-> Branch("new_v",&new_v,"new_v/F");
-   //read the number of entries in the t3
-   Int_t nentries = (Int_t)t3->GetEntries();
-   for (Int_t i = 0; i < nentries; i++){
-      new_v= gRandom->Gaus(0,1);
-      newBranch->Fill();
-   }
-   t3->Write("",TObject::kOverwrite); // save only the new version of
-                                      // the tree
-}
-```
-
-Adding a branch is often not possible because the tree is in a read-only
-file and you do not have permission to save the modified tree with the
-new branch. Even if you do have the permission, you risk loosing the
-original tree with an unsuccessful attempt to save the modification.
-Since trees are usually large, adding a branch could extend it over the
-2GB limit. In this case, the attempt to write the tree fails, and the
-original data is may also be corrupted. In addition, adding a branch to
-a tree enlarges the tree and increases the amount of memory needed to
-read an entry, and therefore decreases the performance. For these
-reasons, ROOT offers the concept of friends for trees (and chains). We
-encourage you to use `TTree::AddFriend` rather than adding a branch
-manually.
-
-### TTree::AddFriend
-
-
-A tree keeps a list of friends. In the context of a tree (or a chain),
-friendship means unrestricted access to the friends data. In this way it
-is much like adding another branch to the tree without taking the risk
-of damaging it. To add a friend to the list, you can use the
-`TTree::AddFriend` method. The **`TTree`** (`tree`) below has two
-friends (`ft1` and `ft2`) and now has access to the variables
-`a,b,c,i,j,k,l` and `m`.
-
-![](pictures/02000101.jpg)
-
-The `AddFriend` method has two parameters, the first is the tree name
-and the second is the name of the ROOT file where the friend tree is
-saved. `AddFriend` automatically opens the friend file. If no file name
-is given, the tree called `ft1` is assumed to be in the same file as the
-original tree.
-
-``` {.cpp}
-   tree.AddFriend("ft1","friendfile1.root");
-```
-
-If the friend tree has the same name as the original tree, you can give
-it an alias in the context of the friendship:
-
-``` {.cpp}
-   tree.AddFriend("tree1 = tree","friendfile1.root");
-```
-
-Once the tree has friends, we can use `TTree::Draw` as if the friend's
-variables were in the original tree. To specify which tree to use in the
-`Draw` method, use the syntax:
-
-``` {.cpp}
-<treeName>.<branchname>.<varname>
-```
-
-If the `variablename` is enough to identify uniquely the variable, you
-can leave out the tree and/or branch name.
-
-For example, these commands generate a 3-d scatter plot of variable
-"`var`" in the **`TTree`** `tree` versus variable `v1 in `TTree ft1`
-versus variable `v2` in **`TTree`** `ft2`.
-
-``` {.cpp}
-   tree.AddFriend("ft1","friendfile1.root");
-   tree.AddFriend("ft2","friendfile2.root");
-   tree.Draw("var:ft1.v1:ft2.v2");
-```
-
-![](pictures/02000102.jpg)The picture illustrates the access of the tree
-and its friends with a `Draw` command.
-
-When `AddFriend` is called, the ROOT file is automatically opened and
-the friend tree (`ft1)` header is read into memory. The new friend
-(`ft1`) is added to the list of friends of `tree`. The number of entries
-in the friend must be equal or greater to the number of entries of the
-original tree. If the friend tree has fewer entries, a warning is given
-and the missing entries are not included in the histogram.
-
-Use `TTree::GetListOfFriends` to retrieve the list of friends from a
-tree.
-
-When the tree is written to file (`TTree::Write`), the friends list is
-saved with it. Moreover, when the tree is retrieved, the trees on the
-friends list are also retrieved and the friendship restored. When a tree
-is deleted, the elements of the friend list are also deleted. It is
-possible to declare a friend tree that has the same internal structure
-(same branches and leaves) as the original tree, and compare the same
-values by specifying the tree.
-
-``` {.cpp}
-   tree.Draw("var:ft1.var:ft2.var");
-```
-
-The example code is in `$ROOTSYS/tutorials/io/tree/tree107_tree.C`. Here is the
-script:
-
-``` {.cpp}
-void tree3w() {
-   // Example of a Tree where branches are variable length arrays
-   // A second Tree is created and filled in parallel.
-   // Run this script with .x tree3.C
-   // In the function treer, the first Tree is open.
-   // The second Tree is declared friend of the first tree.
-   // TTree::Draw is called with variables from both Trees.
-   const Int_t kMaxTrack = 500;
-   Int_t ntrack;
-   Int_t stat[kMaxTrack];
-   Int_t sign[kMaxTrack];
-   Float_t px[kMaxTrack];
-   Float_t py[kMaxTrack];
-   Float_t pz[kMaxTrack];
-   Float_t pt[kMaxTrack];
-   Float_t zv[kMaxTrack];
-   Float_t chi2[kMaxTrack];
-   Double_t sumstat;
-
-   // create the first root file with a tree
-   TFile f("tree107.root","recreate");
-   TTree *t3 = new TTree("t3","Reconst ntuple");
-   t3->Branch("ntrack",&ntrack,"ntrack/I");
-   t3->Branch("stat",stat,"stat[ntrack]/I");
-   t3->Branch("sign",sign,"sign[ntrack]/I");
-   t3->Branch("px",px,"px[ntrack]/F");
-   t3->Branch("py",py,"py[ntrack]/F");
-   t3->Branch("pz",pz,"pz[ntrack]/F");
-   t3->Branch("zv",zv,"zv[ntrack]/F");
-   t3->Branch("chi2",chi2,"chi2[ntrack]/F");
-
-   // create the second root file with a different tree
-   TFile fr("tree3f.root","recreate");
-   TTree *t3f = new TTree("t3f","a friend Tree");
-   t3f->Branch("ntrack",&ntrack,"ntrack/I");
-   t3f->Branch("sumstat",&sumstat,"sumstat/D");
-   t3f->Branch("pt",pt,"pt[ntrack]/F");
-
-   // Fill the trees
-   for (Int_t i=0;i<1000;i++) {
-      Int_t nt = gRandom->Rndm()*(kMaxTrack-1);
-      ntrack = nt;
-      sumstat = 0;
-      // set the values in each track
-      for (Int_t n=0;n<nt;n++) {
-         stat[n] = n%3;
-         sign[n] = i%2;
-         px[n]   = gRandom->Gaus(0,1);
-         py[n]   = gRandom->Gaus(0,2);
-         pz[n]   = gRandom->Gaus(10,5);
-         zv[n]   = gRandom->Gaus(100,2);
-         chi2[n] = gRandom->Gaus(0,.01);
-         sumstat += chi2[n];
-         pt[n]   = TMath::Sqrt(px[n]*px[n] + py[n]*py[n]);
-      }
-      t3->Fill();
-      t3f->Fill();
-   }
-   // Write the two files
-   t3->Print();
-   f.cd();
-   t3->Write();
-   fr.cd();
-   t3f->Write();
-}
-
-// Function to read the two files and add the friend
-void tree107_read()         {
-   TFile *f = new TFile("tree108.root");
-   TTree *t3 = (TTree*)f->Get("t3");
-   // Add the second tree to the first tree as a friend
-   t3->AddFriend("t3f","tree108f.root");
-   // Draw pz which is in the first tree and use pt
-   // in the condition. pt is in the friend tree.
-   t3->Draw("pz","pt>3");
-}
-
-void tree107_read2()
- {
-    auto p = new TPad("p", "p", 0.6, 0.4, 0.98, 0.8);
-    p->Draw();
-    p->cd();
-    auto f1 = TFile::Open("tree108.root");
-    auto f2 = TFile::Open("tree108f.root");
-    auto t3 = f1->Get<TTree>("t3");
-    t3->AddFriend("t3f", f2);
-    t3->Draw("pz", "pt>3");
- }
-
-// This is executed when typing .x tree3.C
-void tree107_tree() {
-   tree107_write();
-   tree107_read();
-   tree107_read2();
-}
-```
-
-## Example 4: A Tree with an Event Class
-
-
-This example is a simplified version of `$ROOTSYS/test/MainEvent.cxx`
-and where Event objects are saved in a tree. The full definition of
-`Event` is in `$ROOTSYS/test`/`Event.h`. To execute this macro, you will
-need the library `$ROOTSYS/test/libEvent.so`. If it does not exist you
-can build the test directory applications by following the instruction
-in the `$ROOTSYS/test/README` file.
-
-In this example we will show
-
--   the difference in splitting or not splitting a branch
--   how to read selected branches of the tree,
--   how to print a selected entry
-
-### The Event Class
-
-
-`Event` is a descendent of **`TObject`**. As such it inherits the data
-members of **`TObject`** and its methods such as `Dump()` and
-`Inspect() `and` Write()`. In addition, because it inherits from
-**`TObject`** it can be a member of a collection. To summarize, the
-advantages of inheriting from a **`TObject`** are:
-
--   Inherit the `Write`, `Inspect`, and `Dump` methods
--   Enables a class to be a member of a ROOT collection
--   Enables RTTI
-
-Below is the list of the `Event` data members. It contains a character
-array, several integers, a floating-point number, and an `EventHeader`
-object. The `EventHeader` class is described in the following paragraph.
-`Event` also has two pointers, one to a **`TClonesArray`** of tracks and
-one to a histogram. The string "`->`" in the comment field of the
-members `*fTracks` and `*fH` instructs the automatic `Streamer` to
-assume that the objects `*fTracks` and `*fH` are never null pointers and
-that `fTracks->Streamer` can be used instead of the more time consuming
-form `R__b << fTracks`.
-
-``` {.cpp}
-class Event : public TObject {
-   private:
-      char                 fType[20];
-      Int_t                fNtrack;
-      Int_t                fNseg;
-      Int_t                fNvertex;
-      UInt_t               fFlag;
-      Float_t              fTemperature;
-      EventHeader          fEvtHdr;
-      TClonesArray        *fTracks;            //->
-      TH1F                *fH;                 //->
-      Int_t                fMeasures[10];
-      Float_t              fMatrix[4][4];
-      Float_t             *fClosestDistance;   //[fNvertex]
-      static TClonesArray *fgTracks;
-      static TH1F         *fgHist;
-      // ... list of methods
-      ClassDef(Event,1)  //Event structure
-};
-```
-
-### The EventHeader Class
-
-
-The `EventHeader` class (also defined in `Event.h`) does not inherit
-from **`TObject`**. Beginning with ROOT 3.0, an object can be placed on
-a branch even though it does not inherit from **`TObject`**. In previous
-releases branches were restricted to objects inheriting from the
-**`TObject`**. However, it has always been possible to write a class not
-inheriting from **`TObject`** to a tree by encapsulating it in a
-**`TObject`** descending class as is the case in `EventHeader` and
-`Event`.
-
-``` {.cpp}
-class EventHeader {
-   private:
-      Int_t   fEvtNum;
-      Int_t   fRun;
-      Int_t   fDate;
-      // ... list of methods
-      ClassDef(EventHeader,1)      //Event Header
-};
-```
-
-### The Track Class
-
-
-The `Track` class descends from **`TObject`** since tracks are in a
-**`TClonesArray`** (i.e. a ROOT collection class) and contains a
-selection of basic types and an array of vertices. Its **`TObject`**
-inheritance enables `Track` to be in a collection and in `Event` is a
-**`TClonesArray`** of `Tracks`.
-
-``` {.cpp}
-class Track : public TObject {
-   private:
-      Float_t   fPx;         //X component of the momentum
-      Float_t   fPy;         //Y component of the momentum
-      Float_t   fPz;         //Z component of the momentum
-      Float_t   fRandom;     //A random track quantity
-      Float_t   fMass2;      //The mass square of this particle
-      Float_t   fBx;         //X intercept at the vertex
-      Float_t   fBy;         //Y intercept at the vertex
-      Float_t   fMeanCharge; //Mean charge deposition of all hits
-      Float_t   fXfirst;     //X coordinate of the first point
-      Float_t   fXlast;      //X coordinate of the last point
-      Float_t   fYfirst;     //Y coordinate of the first point
-      Float_t   fYlast;      //Y coordinate of the last point
-      Float_t   fZfirst;     //Z coordinate of the first point
-      Float_t   fZlast;      //Z coordinate of the last point
-      Float_t   fCharge;     //Charge of this track
-      Float_t   fVertex[3];  //Track vertex position
-      Int_t     fNpoint;     //Number of points for this track
-      Short_t   fValid;      //Validity criterion
-
-      // method definitions ...
-      ClassDef(Track,1)          //A track segment
-};
-```
-
-### Writing the Tree
-
-
-We create a simple tree with two branches both holding `Event` objects.
-One is split and the other is not. We also create a pointer to an
-`Event` object (`event`).
-
-``` {.cpp}
-void tree108_write()
- {
-    // create a Tree file tree108.root
-    TFile f("tree108.root","RECREATE");
-
-    // create a ROOT Tree
-    TTree t4("t4","A Tree with Events");
-
-    // create a pointer to an Event object
-    Event *event = new Event();
-
-    // create two branches, split one.
-    t4.Branch("event_split", &event,16000,99);
-    t4.Branch("event_not_split", &event,16000,0);
-
-    // a local variable for the event type
-    char etype[20];
-
-    // fill the tree
-    for (Int_t ev = 0; ev < 100; ev++) {
-       Float_t sigmat, sigmas;
-       gRandom->Rannor(sigmat, sigmas);
-       Int_t ntrack = Int_t(600 + 600 * sigmat / 120.);
-       Float_t random = gRandom->Rndm(1);
-       sprintf(etype, "type%d", ev%5);
-       event->SetType(etype);
-       event->SetHeader(ev, 200, 960312, random);
-       event->SetNseg(Int_t(10 * ntrack + 20 * sigmas));
-       event->SetNvertex(Int_t(1 + 20 * gRandom->Rndm()));
-       event->SetFlag(UInt_t(random + 0.5));
-       event->SetTemperature(random + 20.);
-
-       for (UChar_t m = 0; m < 10; m++) {
-          event->SetMeasure(m, Int_t(gRandom->Gaus(m, m + 1)));
-       }
-
-       // fill the matrix
-       for (UChar_t i0 = 0; i0 < 4; i0++) {
-          for(UChar_t i1 = 0; i1 < 4; i1++) {
-             event->SetMatrix(i0, i1, gRandom->Gaus(i0 * i1, 1));
-          }
-       }
-
-       // Create and fill the Track objects
-       for (Int_t t = 0; t < ntrack; t++) event->AddTrack(random);
-
-       // Fill the tree
-       t4.Fill();
-
-       // Clear the event before reloading it
-       event->Clear();
-    }
-    // Write the file header
-    f.Write();
-
-    // Print the tree contents
-    t4.Print();
- }
-```
-
-### Reading the Tree
-
-
-First, we check if the shared library with the class definitions is
-loaded. If not we load it. Then we read two branches, one for the number
-of tracks and one for the entire event. We check the number of tracks
-first, and if it meets our condition, we read the entire event. We show
-the fist entry that meets the condition.
-
-
-``` {.cpp}
-void tree108_read()
- {
-    // read the tree generated with tree108_write
-
-    // note that we create the TFile and TTree objects on the heap !
-    // because we want to keep these objects alive when we leave this function.
-    auto f = TFile::Open("tree108.root");
-    auto t4 = f->Get<TTree>("t4");
-
-    // create a pointer to an event object. This will be used
-    // to read the branch values.
-    auto event = new Event();
-
-    // get two branches and set the branch address
-    auto bntrack = t4->GetBranch("fNtrack");
-    auto branch  = t4->GetBranch("event_split");
-    branch->SetAddress(&event);
-
-    Long64_t nevent = t4->GetEntries();
-    Int_t nselected = 0;
-    Int_t nb = 0;
-    for (Long64_t i=0; i<nevent; i++) {
-       // read branch "fNtrack"only
-       bntrack->GetEntry(i);
-
-       // reject events with more than 587 tracks
-       if (event->GetNtrack() > 587)
-          continue;
-
-       // read complete accepted event in memory
-       nb += t4->GetEntry(i);
-       nselected++;
-
-       // print the first accepted event
-       if (nselected == 1)
-          t4->Show();
-
-       // clear tracks array
-       event->Clear();
-    }
-
-    if (gROOT->IsBatch())
-       return;
-    new TBrowser();
-    t4->StartViewer();
- }
-```
-
-Now, let's see how the tree looks like in the tree viewer.
-
-![The tree viewer with tree108_tree example](pictures/03000103.png)
-
-You can see the two branches in the tree in the left panel: the event
-branch is split and hence expands when clicked on. The other branch
-event not split is not expandable and we can not browse the data
-members.
-
-The **`TClonesArray`** of tracks `fTracks` is also split because we set
-the split level to 2. The output on the command line is the result of
-`tree4->Show()`. It shows the first entry with more than 587 tracks:
-
-``` {.cpp}
-======> EVENT:26
- event_split     =
- fUniqueID       = 0
- fBits           = 50331648
- fType[20]       = 116 121 112 101 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- fNtrack         = 585
- fNseg           = 5834
- fNvertex        = 17
- fFlag           = 0
- fTemperature    = 20.044315
- fEvtHdr.fEvtNum = 26
- fEvtHdr.fRun    = 200
- fEvtHdr.fDate   = 960312
- fTracks         = 585
- fTracks.fUniqueID = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-...
-```
-
-## Example 5: Import an ASCII File into a TTree
-
-
-The method `TTree::ReadFile` can be used to automatic define the
-structure of the **`TTree`** and read the data from a formatted ascii
-file.
-
-``` {.cpp}
-Long64_t TTree::ReadFile(const char *filename,
-                         const char *branchDescriptor)
-```
-
-Creates or simply read branches from the file named whose name is passed
-in `'filename'`.
-
-``` {.cpp}
-{
-   gROOT->Reset();
-   TFile *f = new TFile("basic2.root","RECREATE");
-   TH1F *h1 = new TH1F("h1","x distribution",100,-4,4);
-   TTree *T = new TTree("ntuple","data from ascii file");
-   Long64_t nlines = T->ReadFile("basic.dat","x:y:z");
-   printf(" found %lld pointsn",nlines);
-   T->Draw("x","z>2");
-   T->Write();
-}
-```
-
-If `branchDescriptor` is set to an empty string (the default), it is
-assumed that the **`Tree`** descriptor is given in the first line of the
-file with a syntax like: `A/D:Table[2]/F:Ntracks/I:astring/C`.
-
-Otherwise branchDescriptor must be specified with the above syntax.Lines
-in the input file starting with "\#" are ignored. A **`TBranch`** object
-is created for each variable in the expression. The total number of rows
-read from the file is returned.
-
-## Trees in Analysis
-
-
-The methods `TTree::Draw`, `TTree::MakeClass` and
-`TTree::MakeSelector` are available for data analysis using trees. The
-**`TTree::Draw`** method is a powerful yet simple way to look and draw the
-trees contents. It enables you to plot a variable (a leaf) with just one
-line of code. However, the Draw method falls short once you want to look
-at each entry and design more sophisticated acceptance criteria for your
-analysis. For these cases, you can use `TTree::MakeClass`. It creates a
-class that loops over the trees entries one by one. You can then expand
-it to do the logic of your analysis.
-
-The `TTree::MakeSelector` is the recommended method for ROOT data
-analysis. It is especially important for large data set in a parallel
-processing configuration where the analysis is distributed over several
-processors and you can specify which entries to send to each processor.
-With `MakeClass` the user has control over the event loop, with
-`MakeSelector `the tree is in control of the event loop.
-
-## Simple Analysis Using TTree::Draw
-
-
-We will use the tree in `cernstaff.root` that was made by the macro in
-`$ROOTSYS/tutorials/io/tree/tree502_staff.C`.
-
-First, open the file and lists its contents.
-
-``` {.cpp}
-root[] TFile f ("cernstaff.root")
-root[] f.ls()
-TFile**         cernstaff.root
-TFile*         cernstaff.root
-KEY: TTree    T;1     staff data from ascii file
-```
-
-We can see the **`TTree `**"`T`" in the file. We will use it to
-experiment with the **`TTree::Draw`** method, so let's create a pointer to it:
-
-``` {.cpp}
-root[] TTree *MyTree = T
-```
-
-Cling allows us to get simply the object by using it. Here we define a
-pointer to a **`TTree`** object and assign it the value of "`T`", the
-**`TTree`** in the file. Cling looks for an object named "`T`" in the
-current ROOT file and returns it (this assumes that "T" has not
-previously been used to declare a variable or function).
-
-In contrast, in compiled code, you can use:
-
-``` {.cpp}
-   TTree *MyTree;f.GetObject("T",MyTree);
-```
-
-To show the different `Draw` options, we create a canvas with four
-sub-pads. We will use one sub-pad for each `Draw` command.
-
-``` {.cpp}
-root[] TCanvas *myCanvas = new TCanvas()
-root[] myCanvas->Divide(2,2)
-```
-
-We activate the first pad with the `TCanvas::cd` statement:
-
-``` {.cpp}
-root[] myCanvas->cd(1)
-```
-
-We then draw the variable `Cost`:
-
-``` {.cpp}
-root[] MyTree->Draw("C
-```
-
-As you can see, the last call `TTree::Draw` has only one parameter. It
-is a string containing the leaf name. A histogram is automatically
-created as a result of a `TTree::Draw`. The style of the histogram is
-inherited from the **`TTree`** attributes and the current style
-(***`gStyle`***) is ignored. The **`TTree`** gets its attributes from
-the current **`TStyle`** at the time it was created. You can call the
-method `TTree::UseCurrentStyle` to change to the current style rather
-than the **`TTree`** style. (See ***`gStyle`***; see also "Graphics and
-the Graphical User Interface" )
-
-In the next segment, we activate the second pad and draw a scatter plot
-variables:
-
-``` {.cpp}
-root[] myCanvas->cd(2)
-root[] MyTree->Draw("Cost:Age")
-```
-
-This signature still only has one parameter, but it now has two
-dimensions separated by a colon `("x:y")`. The item to be plotted can be
-an expression not just a simple variable. In general, this parameter is
-a string that contains up to three expressions, one for each dimension,
-separated by a colon ("`e1:e2:e3`"). A list of examples follows this
-introduction.
-
-### Using Selection with TTree:Draw
-
-
-Change the active pad to 3, and add a selection to the list of
-parameters of the draw command.
-
-``` {.cpp}
-root[] myCanvas->cd(3)
-root[] MyTree->Draw("Cost:Age","Nation == "FR"")
-```
-
-This will draw the `Cost `vs. `Age` for the entries where the nation is
-equal to "`FR`". You can use any C++ operator, and some functions
-defined in **`TFormula`**, in the selection parameter. The value of the
-selection is used as a weight when filling the histogram. If the
-expression includes only Boolean operations as in the example above, the
-result is 0 or 1. If the result is 0, the histogram is not filled. In
-general, the expression is:
-
-``` {.cpp}
-Selection = "weight *(boolean expression)"
-```
-
-If the Boolean expression evaluates to true, the histogram is filled
-with a weight. If the weight is not explicitly specified it is assumed
-to be 1.
-
-For example, this selection will add 1 to the histogram if x is less
-than y and the square root of z is less than 3.2.
-
-``` {.cpp}
-"x<y && sqrt(z)>3.2"
-```
-
-On the other hand, this selection will add `x+y` to the histogram if the
-square root of z is larger than 3.2.
-
-``` {.cpp}
-"(x+y)*(sqrt(z)>3.2)"
-```
-
-The `Draw` method has its own parser, and it only looks in the current
-tree for variables. This means that any variable used in the selection
-must be defined in the tree. You cannot use an arbitrary global variable
-in the `TTree::Draw` method.
-
-### Using TCut Objects in TTree::Draw
-
-
-The `TTree::Draw` method also accepts **`TCutG`** objects. A
-**`TCut`** is a specialized string object used for **`TTree`**
-selections. A **`TCut`** object has a name and a title. It does not have
-any data members in addition to what it inherits from **`TNamed`**. It
-only adds a set of operators to do logical string concatenation. For
-example, assume:
-
-``` {.cpp}
-TCut cut1 = "x<1"
-TCut cut2 = "y>2"
-```
-
-then
-
-``` {.cpp}
-cut1 && cut2
-//result is the string "(x<1)&&(y>2)"
-```
-
-Operators =, +=, +, \*, !, &&, || are overloaded, here are some
-examples:
-
-``` {.cpp}
-root[] TCut c1 = "x < 1"
-root[] TCut c2 = "y < 0"
-root[] TCut c3 = c1 && c2
-root[] MyTree.Draw("x", c1)
-root[] MyTree.Draw("x", c1 || "x>0")
-root[] MyTree.Draw("x", c1 && c2)
-root[] MyTree.Draw("x", "(x + y)" * (c1 && c2))
-```
-
-### Accessing the Histogram in Batch Mode
-
-
-The `TTree::Draw` method creates a histogram called `htemp` and puts it
-on the active pad. In a batch program, the histogram `htemp` created by
-default, is reachable from the current pad.
-
-``` {.cpp}
-   // draw the histogram
-   nt->Draw("x", "cuts");
-   // get the histogram from the current pad
-   TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp");
-   // now we have full use of the histogram
-   htemp->GetEntries();
-```
-
-If you pipe the result of the `TTree::Draw` into a histogram, the
-histogram is also available in the current directory. You can do:
-
-``` {.cpp}
-   // Draw the histogram and fill hnew with it
-   nt->Draw("x>>hnew","cuts");
-   // get hnew from the current directory
-   TH1F *hnew = (TH1F*)gDirectory->Get("hnew");
-   // or get hnew from the current Pad
-   TH1F *hnew = (TH1F*)gPad->GetPrimitive("hnew");
-```
-
-### Using Draw Options in TTree::Draw
-
-
-The next parameter is the draw option for the histogram:
-
-``` {.cpp}
-root[] MyTree->Draw("Cost:Age","Nation == \"FR\"","surf2");
-```
-
-![Using draw options in trees](pictures/03000104.png)
-
-The draw options are the same as for `TH1::Draw`. See "Draw Options"
-where they are listed. In addition to the draw options defined in
-**`TH1`**, there are three more. The `'prof'` and `'profs'` draw a
-profile histogram (**`TProfile`**) rather than a regular 2D histogram
-(**`TH2D`**) from an expression with two variables. If the expression
-has three variables, a **`TProfile2D`** is generated.
-
-The '`profs`' generates a **`TProfile`** with error on the spread. The
-'`prof`' option generates a **`TProfile`** with error on the mean. The
-"`goff`" option suppresses generating the graphics. You can combine the
-draw options in a list separated by commas. After typing the lines
-above, you should now have a canvas that looks this.
-
-### Superimposing Two Histograms
-
-
-When superimposing two 2-D histograms inside a script with `TTree::Draw`
-and using the "`same`" option, you will need to update the pad between
-`Draw` commands.
-
-``` {.cpp}
-{
-   // superimpose two 2D scatter plots
-   // Create a 2D histogram and fill it with random numbers
-   TH2 *h2 = new TH2D ("h2","2D histo",100,0,70,100,0,20000);
-   for (Int_t i = 0; i < 10000; i++)
-      h2->Fill(gRandom->Gaus(40,10),gRandom->Gaus(10000,3000));
-   // set the color to differentiate it visually
-   h2->SetMarkerColor(kGreen);
-   h2->Draw();
-   // Open the example file and get the tree
-   TFile f("cernstaff.root");
-   TTree *myTree = (TTree*)f.Get("T");
-   // the update is needed for the next draw command to work properly
-   gPad->Update();
-   myTree->Draw("Cost:Age", "","same");
-}
-```
-
-In this example, `h2->Draw` is only adding the object h2 to the pad's
-list of primitives. It does not paint the object on the screen. However,
-`TTree::Draw` when called with option "`same`" gets the current pad
-coordinates to build an intermediate histogram with the right limits.
-Since nothing has been painted in the pad yet, the pad limits have not
-been computed. Calling `pad->Update()` forces the painting of the pad
-and allows `TTree::Draw` to compute the right limits for the
-intermediate histogram.
-
-### Setting the Range in TTree::Draw
-
-
-There are two more optional parameters to the `TTree::Draw` method: one
-is the number of entries and the second one is the entry to start with.
-For example, this command draws 1000 entries starting with entry 100:
-
-``` {.cpp}
-myTree->Draw("Cost:Age", "","",1000,100);
-```
-
-### TTree::Draw Examples
-
-
-The examples below use the `Event.root` file generated by the
-`$ROOTSYS/test/Event` executable and the `Event`, `Track`, and
-`EventHeader` class definitions are in `$ROOTSYS/test/Event.h`. The
-commands have been tested on the split-levels 0, 1, and 9. Each command
-is numbered and referenced by the explanations immediately following the
-examples.
-
-``` {.cpp}
-    // Data members and methods
-1   tree->Draw("fNtrack");
-2   tree->Draw("event.GetNtrack()");
-3   tree->Draw("GetNtrack()");
-4   tree->Draw("fH.fXaxis.fXmax");
-5   tree->Draw("fH.fXaxis.GetXmax()");
-6   tree->Draw("fH.GetXaxis().fXmax");
-7   tree->Draw("GetHistogram().GetXaxis().GetXmax()");
-    // Expressions in the selection parameter
-8   tree->Draw("fTracks.fPx","fEvtHdr.fEvtNum%10 == 0");
-9   tree->Draw("fPx","fEvtHdr.fEvtNum%10 == 0");
-    // Two dimensional arrays defined as:
-    //   Float_t fMatrix[4][4] in Event class
-10  tree->Draw("fMatrix");
-11  tree->Draw("fMatrix[ ][ ]");
-12  tree->Draw("fMatrix[2][2]");
-13  tree->Draw("fMatrix[ ][0]");
-14  tree->Draw("fMatrix[1][ ]");
-    // using two arrays... Float_t  fVertex[3];  in Track class
-15  tree->Draw("fMatrix - fVertex");
-16  tree->Draw("fMatrix[2][1]  - fVertex[5][1]");
-17  tree->Draw("fMatrix[ ][1]  - fVertex[5][1]");
-18  tree->Draw("fMatrix[2][ ]  - fVertex[5][ ]");
-19  tree->Draw("fMatrix[ ][2]  - fVertex[ ][1]");
-20  tree->Draw("fMatrix[ ][2]  - fVertex[ ][ ]");
-21  tree->Draw("fMatrix[ ][ ]  - fVertex[ ][ ]");
-    // variable length arrays
-22  tree->Draw("fClosestDistance");
-23  tree->Draw("fClosestDistance[fNvertex/2]");
-    // mathematical expressions
-24  tree->Draw("sqrt(fPx*fPx + fPy*fPy + fPz*fPz))");
-    // external function call
-25  tree->Draw("TMath::BreitWigner(fPx,3,2)");
-    // strings
-26  tree->Draw("fEvtHdr.fEvtNum","fType=="type1" ");
-27  tree->Draw("fEvtHdr.fEvtNum","strstr(fType,"1" ");
-    // Where fPoints is defined in the track class:
-    //        Int_t  fNpoint;
-    //        Int_t *fPoints; [fNpoint]
-28  tree->Draw("fTracks.fPoints");
-29  tree->Draw("fTracks.fPoints - fTracks.fPoints[][fAvgPoints]");
-30  tree->Draw("fTracks.fPoints[2][]- fTracks.fPoints[][55]");
-31  tree->Draw("fTracks.fPoints[][] - fTracks.fVertex[][]");
-    // selections
-32  tree->Draw("fValid&0x1","(fNvertex>10) && (fNseg<=6000)");
-33  tree->Draw("fPx","(fBx>.4) || (fBy<=-.4)");
-34  tree->Draw("fPx","fBx*fBx*(fBx>.4) + fBy*fBy*(fBy<=-.4)");
-35  tree->Draw("fVertex","fVertex>10");
-36  tree->Draw("fPx[600]");
-37  tree->Draw("fPx[600]","fNtrack>600");
-    // alphanumeric bin histogram
-    // where Nation is a char* indended to be used as a string
-38  tree->Draw("Nation");
-    // where MyByte is a char* intended to be used as a byte
-39  tree->Draw("MyByte + 0");
-    // where fTriggerBits is a data member of TTrack of type TBits
-40  tree->Draw("fTracks.fTriggerBits");
-    // using alternate values
-41  tree->Draw("fMatrix-Alt$(fClosestDistance,0)");
-    // using meta information about the formula
-42  tree->Draw("fMatrix:Iteration$")
-43 T->Draw("fLastTrack.GetPx():fLastTrack.fPx");
-44 T->Scan("((Track*)(fLastTrack@.GetObject())).GetPx()","","");
-45 tree->Draw("This->GetReadEntry()");
-46  tree->Draw("mybr.mystring");
-47  tree->Draw("myTimeStamp");
-```
-
-#### Explanations:
-
-1. **`tree->Draw("fNtrack");`**
-
-It fills the histogram with the number of tracks for each entry.
-`fNtrack` is a member of event.
-
-2. **`tree->Draw("event.GetNtrack()");`**
-
-Same as case 1, but use the method of event to get the number of tracks.
-When using a method, you can include parameters for the method as long
-as the parameters are literals.
-
-3. **`tree->Draw("GetNtrack()");`**
-
-Same as case 2, the object of the method is not specified. The command
-uses the first instance of the `GetNtrack` method found in the objects
-stored in the tree. We recommend using this shortcut only if the method
-name is unique.
-
-4. **`tree->Draw("fH.fXaxis.fXmax");`**
-
-Draw the data member of a data member. In the tree, each entry has a
-histogram. This command draws the maximum value of the X-axis for each
-histogram.
-
-5. **`tree->Draw("fH.fXaxis.GetXmax()");`**
-
-Same as case 4, but use the method of a data member.
-
-6. **`tree->Draw("fH.GetXaxis().fXmax");`**
-
-The same as case 4: a data member of a data member retrieved by a
-method.
-
-7. **`tree->Draw("GetHistogram().GetXaxis().GetXmax()");`**
-
-Same as case 4, but using methods.
-
-8. **`tree->Draw("fTracks.fPx","fEvtHdr.fEvtNum%10 == 0");`**
-
-Use data members in the expression and in the selection parameter to
-plot `fPx` or all tracks in every 10th entry. Since `fTracks` is a
-**`TClonesArray`** of `Tracks`, there will be d values of `fPx` for each
-entry.
-
-9. **`tree->Draw("fPx","fEvtHdr.fEvtNum%10 == 0");`**
-
-Same as case 8, use the name of the data member directly.
-
-10. **`tree->Draw("fMatrix");`**
-
-When the index of the array is left out or when empty brackets are used
-`[]`, all values of the array are selected. Draw all values of `fMatrix`
-for each entry in the tree. If `fMatrix` is defined as:
-`Float_t fMatrix[4][4]`, all 16 values are used for each entry.
-
-11. **`tree->Draw("fMatrix[ ][ ]");`**
-
-The same as case 10, all values of `fMatrix` are drawn for each entry.
-
-12. **`tree->Draw("fMatrix[2][2]");`**
-
-The single element at `fMatrix[2][2]` is drawn for each entry.
-
-13. **`tree->Draw("fMatrix[][0]");`**
-
-Four elements of `fMatrix` are used: `fMatrix[1][0]`, `fMatrix[2][0]`,
-`fMatrix[3][0]`, `fMatrix[4][0]`.
-
-14. **`tree->Draw("fMatrix[1][ ]");`**
-
-Four elements of `fMatrix` are used: `fMatrix[1][0]`, `fMatrix[1][2]`,
-`fMatrix[1][3]`, `fMatrix[1][4]`.
-
-15. **`tree->Draw("fMatrix - fVertex");`**
-
-With two arrays and unspecified element numbers, the number of selected
-values is the minimum of the first dimension times the minimum of the
-second dimension. In this case `fVertex` is also a two dimensional array
-since it is a data member of the tracks array. If `fVertex` is defined
-in the track class as: `Float_t *fVertex[3]`, it has `fNtracks` x 3
-elements. `fMatrix` has 4 x 4 elements. This case, draws 4 (the smaller
-of `fNtrack` and 4) times 3 (the smaller of 4 and 3), meaning 12
-elements per entry. The selected values for each entry are:
-
-`fMatrix[0][0] - fVertex[0][0]`
-
-`fMatrix[0][1] - fVertex[0][1]`
-
-`fMatrix[0][2] - fVertex[0][2]`
-
-`fMatrix[1][0] - fVertex[1][0]`
-
-`fMatrix[1][1] - fVertex[1][1]`
-
-`fMatrix[1][2] - fVertex[1][2]`
-
-`fMatrix[2][0] - fVertex[2][0]`
-
-`fMatrix[2][1] - fVertex[2][1]`
-
-`fMatrix[2][2] - fVertex[2][2]`
-
-`fMatrix[3][0] - fVertex[3][0]`
-
-`fMatrix[3][1] - fVertex[3][1]`
-
-`fMatrix[3][2] - fVertex[3][2]`
-
-16. **`tree->Draw("fMatrix[2][1] - fVertex[5][1]");`**
-
-This command selects one value per entry.
-
-17. **`tree->Draw("fMatrix[ ][1] - fVertex[5][1]");`**
-
-The first dimension of the array is taken by the `fMatrix`.
-
-`fMatrix[0][1] - fVertex[5][1]`
-
-`fMatrix[1][1] - fVertex[5][1]`
-
-`fMatrix[2][1] - fVertex[5][1]`
-
-`fMatrix[3][1] - fVertex[5][1]`
-
-18. **`tree->Draw("("fMatrix[2][ ] - fVertex[5][ ]");`**
-
-The first dimension minimum is 2, and the second dimension minimum is 3
-(from `fVertex`). Three values are selected from each entry:
-
-`fMatrix[2][0] - fVertex[5][0]`
-
-`fMatrix[2][1] - fVertex[5][1]`
-
-`fMatrix[2][2] - fVertex[5][2]`
-
-19. **`tree->Draw("fMatrix[ ][2] - fVertex[ ][1]")`**
-
-This is similar to case 18. Four values are selected from each entry:
-
-`fMatrix[0][2] - fVertex[0][1]`
-
-`fMatrix[1][2] - fVertex[1][1]`
-
-`fMatrix[2][2] - fVertex[2][1]`
-
-`fMatrix[3][2] - fVertex[3][1]`
-
-20. **`tree->Draw("fMatrix[ ][2] - fVertex[ ][ ]")`**
-
-This is similar to case 19. Twelve values are selected (4x3) from each
-entry:
-
-`fMatrix[0][2] - fVertex[0][0]`
-
-`fMatrix[0][2] - fVertex[0][1]`
-
-`fMatrix[0][2] - fVertex[0][2]`
-
-`fMatrix[1][2] - fVertex[1][0]`
-
-`fMatrix[1][2] - fVertex[1][1]`
-
-`fMatrix[1][2] - fVertex[1][2]`
-
-`fMatrix[2][2] - fVertex[2][0]`
-
-`fMatrix[2][2] - fVertex[2][1]`
-
-`fMatrix[2][2] - fVertex[2][2]`
-
-`fMatrix[3][2] - fVertex[3][0]`
-
-`fMatrix[3][2] - fVertex[3][1]`
-
-`fMatrix[3][2] - fVertex[3][2]`
-
-21. **`tree->Draw("fMatrix[ ][ ] - fVertex[ ][ ]")`**
-
-This is the same as case 15. The first dimension minimum is 4 (from
-`fMatrix`), and the second dimension minimum is 3 (from `fVertex`).
-Twelve values are selected from each entry.
-
-22. **`tree->Draw("fClosestDistance")`**
-
-This event data member `fClosestDistance` is a variable length array:
-
-`Float_t  *fClosestDistance;   //[fNvertex]`
-
-This command selects all elements, but the number per entry depends on
-the number of vertices of that entry.
-
-23. **`tree->Draw("fClosestDistance[fNvertex/2]")`**
-
-With this command the element at `fNvertex/2` of the
-`fClosestDistance `array is selected. Only one per entry is selected.
-
-24. **`tree->Draw("sqrt(fPx*fPx + fPy*fPy + fPz*fPz)")`**
-
-This command shows the use of a mathematical expression. It draws the
-square root of the sum of the product.
-
-25. **`tree->Draw("TMath::BreitWigner(fPx,3,2)")`**
-
-The formula can contains call to a function that takes numerical
-arguments and returns a numerical value. The function needs to be
-declared to the dictionary and need to be available from the global
-namespace. In particular, global functions and public static member
-functions can be called.
-
-26. **`tree->Draw("fEvtHdr.fEvtNum","fType=="type1" ")`**
-
-You can compare strings, using the symbols == and !=, in the first two
-parameters of the `Draw` command (`TTreeFormula`). In this case,
-the event number for ‘type1' events is plotted.
-
-27. **`tree->Draw("fEvtHdr.fEvtNum","strstr(fType,"1") ")`**
-
-To compare strings, you can also use `strstr`. In this case, events
-having a '1' in `fType` are selected.
-
-28. **`tree->Draw("fTracks.fPoints")`**
-
-If `fPoints` is a data member of the `Track` class declared as:
-
-`Int_t  fNpoint;`
-
-`Int_t *fPoints; [fNpoint]`
-
-The size of the array `fPoints` varies with each track of each event.
-This command draws all the value in the `fPoints` arrays.
-
-29. **`tree->Draw("fTracks.fPoints - fTracks.fPoints[][fAvgPoints]");`**
-
-`When fAvgPoints` is a data member of the `Event` class, this example
-selects:
-
-`fTracks[0].fPoints[0] - fTracks[0].fPoint[fAvgPoints]`
-
-`fTracks[0].fPoints[1] - fTracks[0].fPoint[fAvgPoints]`
-
-`fTracks[0].fPoints[2] - fTracks[0].fPoint[fAvgPoints]`
-
-`fTracks[0].fPoints[3] - fTracks[0].fPoint[fAvgPoints]`
-
-`fTracks[0].fPoints[4] - fTracks[0].fPoint[fAvgPoints]`
-
-`...`
-
-`fTracks[0].fPoints[max0]- fTracks[0].fPoint[fAvgPoints]`
-
-`...`
-
-`fTracks[1].fPoints[0] - fTracks[1].fPoint[fAvgPoints]`
-
-`fTracks[1].fPoints[1] - fTracks[1].fPoint[fAvgPoints]`
-
-`fTracks[1].fPoints[2] - fTracks[1].fPoint[fAvgPoints]`
-
-`fTracks[1].fPoints[3] - fTracks[1].fPoint[fAvgPoints]`
-
-`fTracks[1].fPoints[4] - fTracks[1].fPoint[fAvgPoints]`
-
-`...`
-
-`fTracks[1].fPoints[max1]- fTracks[1].fPoint[fAvgPoints]`
-
-`...`
-
-`fTracks[fNtrack-1].fPoints[0] - fTracks[fNtrack-1].fPoint[fAvgPoints]`
-
-`fTracks[fNtrack-1].fPoints[1] - fTracks[fNtrack-1].fPoint[fAvgPoints]`
-
-`fTracks[fNtrack-1].fPoints[2] - fTracks[fNtrack-1].fPoint[fAvgPoints]`
-
-`fTracks[fNtrack-1].fPoints[3] - fTracks[fNtrack-1].fPoint[fAvgPoints]`
-
-`fTracks[fNtrack-1].fPoints[4] - fTracks[fNtrack-1].fPoint[fAvgPoints]`
-
-`...`
-
-`fTracks[fNtrack-1].fPoints[maxn] - fTracks[fNtrack-1].fPoint[fAvgPoints]`
-
-Where` max0`, `max1`, `... max n`, is the size of the` fPoints `array for
-the respective track`.`
-
-30. **`tree->Draw("fTracks.fPoints[2][]- fTracks.fPoints[][55]") `**
-
-For each event, this expression is selected:
-
-`fTracks[2].fPoints[0] - fTracks[0].fPoints[55]`
-
-`fTracks[2].fPoints[1] - fTracks[1].fPoints[55]`
-
-`fTracks[2].fPoints[2] - fTracks[2].fPoints[55]`
-
-`fTracks[2].fPoints[3] - fTracks[3].fPoints[55]`
-
-`  ...`
-
-`fTracks[2].fPoints[max] - fTracks[max].fPoints[55]`
-
-where max is the minimum of `fNtrack` and `fTracks[2].fNpoint`.
-
-31. **`tree->Draw("fTracks.fPoints[][] - fTracks.fVertex[][]")`**
-
-For each event and each track, this expression is selected. It is the
-difference between `fPoints` and of `fVertex`. The number of elements
-used for each track is the minimum of `fNpoint` and 3 (the size of the
-`fVertex` array).
-
-`fTracks[0].fPoints[0] - fTracks[0].fVertex[0]`
-
-`fTracks[0].fPoints[1] - fTracks[0].fVertex[1]`
-
-`fTracks[0].fPoints[2] - fTracks[0].fVertex[2]`
-
-`// with fTracks[1].fNpoint==7`
-
-`fTracks[1].fPoints[0] - fTracks[1].fVertex[0]`
-
-`fTracks[1].fPoints[1] - fTracks[1].fVertex[1]`
-
-`fTracks[1].fPoints[2] - fTracks[1].fVertex[2]`
-
-`// with fTracks[1].fNpoint==5`
-
-`fTracks[2].fPoints[0] - fTracks[2].fVertex[0]`
-
-`fTracks[2].fPoints[1] - fTracks[2].fVertex[1]`
-
-`// with fTracks[2].fNpoint==2`
-
-`fTracks[3].fPoints[0] - fTracks[3].fVertex[0]`
-
-`// with fTracks[3].fNpoint==1`
-
-`fTracks[4].fPoints[0] - fTracks[4].fVertex[0]`
-
-`fTracks[4].fPoints[1] - fTracks[4].fVertex[1]`
-
-`fTracks[4].fPoints[2] - fTracks[4].fVertex[2] `
-
-`// with fTracks[4].fNpoint==3`
-
-32. **`tree->Draw("fValid&0x1","(fNvertex>10) && (fNseg<=6000)")`**
-
-You can use bit patterns (`&,|,<<`) or Boolean operation.
-
-33. **`tree->Draw("fPx","(fBx>.4) || (fBy<=-.4)");`**
-
-34. **`tree->Draw("fPx","fBx*fBx*(fBx>.4) + fBy*fBy*(fBy<=-.4)");`**
-
-The selection argument is used as a weight. The expression returns a
-multiplier and in case of a Boolean the multiplier is either 0 (for
-false) or 1 (for true). The first command draws `fPx` for the range
-between with conditions on `fBx` and `fBy`, the second command draws `fPx`
-for the same conditions, but adds a weight using the result of the second
-expression.
-
-35. **`tree->Draw("fVertex","fVertex>10")`**
-
-When using arrays in the selection and the expression, the selection is
-applied to each element of the array.
-
-`if (fVertex[0]>10) fVertex[0]`
-
-`if (fVertex[1]>10) fVertex[1]`
-
-`if (fVertex[2]>10) fVertex[2]`
-
-36. **`tree->Draw("fPx[600]")`**
-
-37. **`tree->Draw("fPx[600]","fNtrack > 600")`**
-
-When using a specific element for a variable length array the entries
-with fewer elements are ignored. Thus these two commands are equivalent.
-
-38. **`tree->Draw("Nation")`**
-
-`Nation` is a `char*` branch. When drawing a `char*` it will plot an
-alphanumeric histogram, of the different value of the string `Nation`.
-The axis will have the `Nation` values. See "Histograms".
-
-39. **`tree->Draw("MyChar +0")`**
-
-If you want to plot a char\* variable as a byte rather than a string,
-you can use the syntax above.
-
-40. **`tree->Draw("fTracks.fTriggerBits")`**
-
-`fTriggerBits` is a data member of **`TTrack`** of type **`TBits`**.
-Objects of class **`TBits`** can be drawn directly. This command will
-create a 1D histogram from 0 to `nbits` which is filled for each
-non-null bit-number.
-
-41. **`tree->Draw("fMatrix-Alt$(fClosestDistance,0)")`**
-
-`Alt$(primary,alternate)` returns the value of "`primary`" if it is
-available for the current iteration; otherwise return the value of
-"`alternate`". Assuming that `fClosestDistance` is a smaller array than
-`fMatrix`. This example will draw `fMatrix[i]+fClosestDistance[i]` for
-`i` less than the size of `fClosestDistance`, and will draw
-`fMatrix[i]+0` for the other value of `i`.
-
-42. **`tree->Draw("fClosestDistance:Iteration$")`**
-
-This example draws a 2D plot with, for all entries,
-`fClosestDistance[i]:i` for each value of `i` between 0 and the size of
-`fClosestDistance`. `Iterations$` is one of four special variables
-giving some indications of the state of the loops implied by the
-formula:
-
-`Entry$    :` return the current entry number (`TTree::GetReadEntry()`)
-
-`Entries$  :` return the total number of entries (`TTree::GetEntries()`)
-
-`Length$   :` return the total number of element of this formula for
-this entry
-
-`Iteration$:` return the current iteration over this formula for this
-entry (i.e. varies from 0 to `Length$`).
-
-43. **`tree->Draw("fLastTrack.GetPx():fLastTrack.fPx");`**
-
-**`TRef`** and **`TRefArray`** are automatically deferenced and this
-shows the value of the `fPx` of the track referenced by `fLastTrack`. To
-access the **`TRef`** object itself use the '`@`' notation (see next
-example). This auto dereferencing can be extended (via an implementation
-of **`TVirtualRefProxy`**) to any reference type.
-
-44. **`tree->Scan("((Track*)(fLastTrack@.GetObject())).GetPx()","","");`**
-
-Will cast the return value of `GetObject()` (which happens to be
-**`TObject*`** in this case) before requesting the `GetPx()` member
-functions.
-
-45. **`tree->Draw("This->GetReadEntry()");`**
-
-You can refer to the tree (or chain) containing the data by using the
-string '`This`'. You can also call any **`TTree`** methods. Next example
-will display the name of the first '`user info`' object:
-
-`tree->Draw("This->GetUserInfo()->At(0)->GetName()");`
-
-46.  **`tree->Draw("mybr.mystring");`**
-
-**`TString`** and `std::string` object are plotted directly. The example
-45 draws the same results - i.e. an histogram whose labels are the
-string value of '`mystring`':
-
-`tree->Draw("mybr.mystring.c_str()");`
-
-or
-
-`tree->Draw("mybr.mytstring.Data()");`
-
-47.  **`tree->Draw("myTimeStamp");`**
-
-You can plot plot objects of any class which has either `AsDouble` or
-`AsString` (`AsDouble` has priority). For such a class (for example
-**`TTimeStamp`**), the line 46 will plot the same as:
-
-`tree->Draw("myTimeStamp.AsDouble");`
-
-`AsString` can be returning either a `char*`, or a **`TString`** or an
-`std::string`.
-
-### Multiple variables visualisation
-
-
-This section presents the visualization technique available in ROOT
-to represent multiple variables (>4) data sets.
-
-#### Spider (Radar) Plots
-
-Spider plots (sometimes called “web-plots” or “radar plots”) are used
-to compare series of data points (events). They use the human ability
-to spot un-symmetry.
-
-![Example of spider plot.](pictures/spider1.png)
-
-Variables are represented on individual axes displayed along a circle.
-For each variable the minimum value sits on the circle’s center, and
-the maximum on the circle’s radius. Spider plots are not suitable for
-an accurate graph reading since, by their nature, it can be difficult
-to read out very detailed values, but they give quickly a global view
-of an event in order to compare it with the others. In ROOT the spider
-plot facility is accessed from the tree viewer GUI. The variables to
-be visualized are selected in the tree viewer and can be scanned using
-the spider plot button.
-
-![The tree viewer Graphical User Interface and the Spider Plot Editor.](pictures/spider2.png)
-
-The spider plot graphics editor provides two tabs to interact with
-the spider plots’ output: the tab “Style” defining the spider layout
-and the tab “Browse” to navigate in the tree.
-
-#### Parallel Coordinates Plots
-\index{parallel coordinates}
-
-The Parallel Coordinates Plots are a common way of studying and
-visualizing multiple variables data sets. They were proposed by in
-A.Inselberg in 1981 as a new way to represent multi-dimensional
-information. In traditional Cartesian coordinates, axes are mutually
-perpendicular. In Parallel coordinates, all axes are parallel which
-allows representing data in much more than three dimensions. To show
-a set of points in Parallel Coordinates, a set of parallel lines is
-drawn, typically vertical and equally spaced. A point in n-dimensional
-space is represented as a polyline with vertices on the parallel axes.
-The position of the vertex on the i-th axis corresponds to the i-th
-coordinate of the point. The three following figures show some very
-simple examples:
-
-![The Parallel Coordinates representation of the six dimensional point `(-5,3,4,2,0,1)`.](pictures/para1.png)
-
-![The line `y = -3x+20` and a circle in Parallel Coordinates.](pictures/para2.png)
-
-The Parallel Coordinates technique is good at: spotting irregular
-events, seeing the data trend, finding correlations and clusters. Its
-main weakness is the cluttering of the output. Because each “point” in
-the multidimensional space is represented as a line, the output is very
-quickly opaque and therefore it is difficult to see the data clusters.
-Most of the work done about Parallel Coordinates is to find techniques
-to reduce the output’s cluttering. The Parallel Coordinates plots in
-ROOT have been implemented as a new plotting option “PARA” in the
-`TTree::Draw()method`. To demonstrate how the Parallel Coordinates
-works in ROOT we will use the tree produced by the following
-“pseudo C++” code:
-
-``` {.cpp}
-void parallel_example() {
-   TNtuple *nt = new TNtuple("nt","Demo ntuple","x:y:z:u:v:w:a:b:c");
-   for (Int_t i=0; i<3000; i++) {
-      nt->Fill(   rnd,   rnd,   rnd,    rnd,    rnd,    rnd, rnd, rnd, rnd );
-      nt->Fill(   s1x,   s1y,   s1z,    s2x,    s2y,    s2z, rnd, rnd, rnd );
-      nt->Fill(   rnd,   rnd,   rnd,    rnd,    rnd,    rnd, rnd, s3y, rnd );
-      nt->Fill( s2x-1, s2y-1,   s2z, s1x+.5, s1y+.5, s1z+.5, rnd, rnd, rnd );
-      nt->Fill(   rnd,   rnd,   rnd,    rnd,    rnd,    rnd, rnd, rnd, rnd );
-      nt->Fill( s1x+1, s1y+1, s1z+1,  s3x-2,  s3y-2,  s3z-2, rnd, rnd, rnd );
-      nt->Fill(   rnd,   rnd,   rnd,    rnd,    rnd,    rnd, s3x, rnd, s3z );
-      nt->Fill(   rnd,   rnd,   rnd,    rnd,    rnd,    rnd, rnd, rnd, rnd );
-   }
-```
-
-The data set generated has:
-
--    9 variables: x, y, z, u, v, w, a, b, c.
--    3000*8 = 24000 events.
--    3 sets of random points distributed on spheres: s1, s2, s3
--    Random values (noise): rnd
--    The variables a,b,c are almost completely random. The variables a
-and c are correlated via the 1st and 3rd coordinates of the 3rd “sphere” s3.
-
-The command used to produce the Parallel Coordinates plot is:
-
-``` {.cpp}
-   nt->Draw("x:a:y:b:z:u:c:v:w","","PARA");
-```
-
-![Cluttered output produced when all the tree events are plotted.](pictures/para3.png)
-
-If the 24000 events are plotted as solid lines and no special techniques
-are used to clarify the picture, the result is the previous picture
-which is very cluttered and useless. To improve the readability of the
-Parallel Coordinates output and to explore interactively the data set,
-many techniques are available. We have implemented a few in ROOT. First
-of all, in order to show better where the clusters on the various axes
-are, a 1D histogram is associated to each axis. These histograms
-(one per axis) are filled according to the number of lines passing
-through the bins.
-
-![The histogram’s axis can be represented with colors or as bar charts.](pictures/para4.png)
-
-These histograms can be represented which colors (get from a palette
-according to the bin contents) or as bar charts. Both representations
-can be cumulated on the same plot. This technique allows seeing clearly
-where the clusters are on an individual axis but it does not give any
-hints about the correlations between the axes.
-
-Avery simple technique allows to make the clusters appearing:
-Instead of painting solid lines we paint dotted lines. The cluttering of
-each individual line is reduced and the clusters show clearly as we can
-see on the next figure. The spacing between the dots is a parameter which
-can be adjusted in order to get the best results.
-
-![Using dotted lines is a very simple method to reduce the cluttering.](pictures/para5.png)
-
-Interactivity is a very important aspect of the Parallel Coordinates plots.
-To really explore the data set it is essential to act directly with the
-events and the axes. For instance, changing the axes order may show clusters
-which were not visible in a different order. On the next figure the axes
-order has been changed interactively. We can see that many more clusters
-appear and all the “random spheres” we put in the data set are now
-clearly visible. Having moved the variables `u,v,w` after the variables
-`x,y,z` the correlation between these two sets of variables is clear also.
-
-![Axis order is very important to show clusters.](pictures/para6.png)
-
-To pursue further data sets exploration we have implemented the possibility
-to define selections interactively. A selection is a set of ranges combined
-together. Within a selection, ranges along the same axis are combined with
-logical OR, and ranges on different axes with logical AND. A selection is
-displayed on top of the complete data set using its own color. Only the
-events fulfilling the selection criteria (ranges) are displayed. Ranges
-are defined interactively using cursors, like on the first axis on the
-figure. Several selections can be defined at the same time,
-each selection having its own color.
-
-![Selections are set of ranges which can be defined interactively.](pictures/para7.png)
-
-Several selections can been defined. Each cluster is now clearly visible
-and the zone with crossing clusters is now understandable whereas,
-without any selection or with only a single one, it was not easy to
-understand.
-
-![Several selections can be defined each of them having its own color.](pictures/para8.png)
-
-Interactive selections on Parallel Coordinates are a powerful tool because
-they can be defined graphically on many variables (graphical cuts in ROOT can
-be defined on two variables only) which allow a very accurate events
-filtering. Selections allow making precise events choices: a single outlying
-event is clearly visible when the lines are displayed as “solid” therefore
-it is easy to make cuts in order to eliminate one single event from a
-selection. Such selection (to filter one single event) on a scatter plot
-would be much more difficult.
-
-![Selections allow to easily filter one single event.](pictures/para9.png)
-
-Once a selection has been defined, it is possible to use it to generate a
-`TEntryList` which is applied on the tree and used at drawing time. In our
-example the selection we defined allows to select exactly the two
-correlated “random spheres”.
-
-![Output of `nt->Draw(“x:y:z”)` and `nt->Draw(“u:v:w”)` after applying the selection.](pictures/para10.png)
-
-Another technique has been implemented in order to show clusters when
-the picture is cluttered. A weight is assigned to each event. The weight
-value is computed as:
-$$
-weight = \sum_{i=1}^{n} b_i
-$$
-
-Where:
-
--    bi is the content of bin crossed by the event on the i-th axis.
--    n is the number of axis.
-
-The events having the bigger weights are those belonging to clusters.
-It is possible to paint only the events having a weight above a given
-value and the clusters appear. The next example “weight cut” applied on
-the right plot is 50. Only the events with a weight greater than 50 are displayed.
-
-![Applying a “weight cut” makes the clusters visible.](pictures/para11.png)
-
-In case only a few events are displayed, drawing them as smooth curves
-instead of straight lines helps to differentiate them.
-
-![Zoom on a Parallel Coordinates plot detail: curves differentiate better events.](pictures/para12.png)
-
-Interactivity and therefore the Graphical User Interface are very important
-to manipulate the Parallel Coordinates plots.  The ROOT framework allows
-to easily implement the direct interactions on the graphical area and the
-graphical editor facility provides dedicated GUI.
-
-![Parallel Coordinates graphical editors.](pictures/para13.png)
-
-Transparency is very useful with parallel coordinates plots. It allows to
-show clearly the clusters.
-\index{transparency!parallel coordinates}
-
-![Parallel Coordinates with transparency.](pictures/para14.png)
-
-
-
-#### Box (Candle) Plots
-\index{candle plot}
-\index{candle stick plot}
-\index{box-and whisker plot}
-
-A Box Plot (also known as a “box-and whisker” plot or “candle stick” plot)
-is a convenient way to describe graphically a data distribution (D) with only
-the five numbers. It was invented in 1977 by John Tukey. The five numbers are:
-
-1. The minimum value of the distribution D (Min).
-2. The lower quartile (Q1): 25% of the data points in D are less than Q1.
-3. The median (M): 50% of the data points in D are less than M.
-4. The upper quartile (Q3): 75% of the data points in D are less than Q3.
-5. The maximum value of the distribution D (Max).
-
-![A box plot describes a distribution with only five numbers. ](pictures/bp1.png)
-
-In ROOT Box Plots (Candle Plots) can be produced from a TTree using the
-“candle” option in TTree::Draw().
-
-``` {.cpp}
-  tree->Draw(“px:cos(py):sin(pz)”,””,”candle”);
-```
-
-
-
-### Using TTree::Scan
-\index{tree!scan}
-
-`TTree::Scan` can be used to print the content of the tree's entries
-optional passing a selection.
-
-``` {.cpp}
-root[] MyTree->Scan();
-```
-
-will print the first 8 variables of the tree.
-
-``` {.cpp}
-root[] MyTree->Scan("*");
-```
-
-will print all the variable of the tree.
-
-Specific variables of the tree can be explicit selected by list them in
-column separated list:
-
-``` {.cpp}
-root[] MyTree->Scan("var1:var2:var3");
-```
-
-will print the values of `var1`, `var2` and `var3`. A selection can be
-applied in the second argument:
-
-``` {.cpp}
-root[] MyTree->Scan("var1:var2:var3","var1==0");
-```
-
-will print the values of `var1`, `var2` and `var3` for the entries where
-var1 is exactly 0.
-
-`TTree::Scan` returns the number of entries passing the selection. By
-default 50 rows are shown before `TTree::Scan` pauses and ask you to
-press the Enter key to see the next 50 rows. You can change the default
-number of rows to be shown before \<CR\> via
-`mytree->SetScanfield(maxrows)` where maxrows is 50 by default. If
-maxrows is set to 0 all rows of the **`Tree`** are shown. This option is
-interesting when dumping the contents of a Tree to an ascii file, eg
-from the command line:
-
-``` {.cpp}
-root[] tree->SetScanField(0);
-root[] tree->Scan("*"); >tree.log
-```
-
-will create a file `tree.log`.
-
-Arrays (within an entry) are printed in their linear forms. If several
-arrays with multiple dimensions are printed together, they will NOT be
-synchronized. For example, with a tree containing `arr1[4][2] `and
-`arr2[2][3]`,
-
-``` {.cpp}
-root[] MyTree("arr1:arr2");
-```
-
-will results in a printing similar to:
-
-``` {.cpp}
-************************************************
-*    Row   * Instance *      arr1 *      arr2 *
-***********************************************
-*        x *        0 * arr1[0][0]* arr2[0][0]*
-*        x *        1 * arr1[0][1]* arr2[0][1]*
-*        x *        2 * arr1[1][0]* arr2[0][2]*
-*        x *        3 * arr1[1][1]* arr2[1][0]*
-*        x *        4 * arr1[2][0]* arr2[1][1]*
-*        x *        5 * arr1[2][1]* arr2[1][2]*
-*        x *        6 * arr1[3][0]*           *
-*        x *        7 * arr1[3][1]*           *
-```
-
-However, if there is a selection criterium which is an array, then all
-the formulas will be synchronized with the selection criterium (see
-**`TTree::Draw` for more information).**
-
-The third parameter of `TTree::Scan` can be use to specific the layout
-of the table:
-
--   `lenmax=dd` - where 'dd' is the maximum number of elements per array
-    that should be printed. If 'dd' is 0, all elements are printed (this
-    is the default).
-
--   `colsize=ss` - where 'ss' will be used as the default size for all
-    the column. If this options is not specified, the default column
-    size is 9.
-
--   `precision=pp` - where 'pp' will be used as the default 'precision'
-    for the printing format.
-
--   `col=xxx` - where '`xxx`' is colon (:) delimited list of printing
-    format for each column if no format is specified for a column, the
-    default is used.
-
-For example:
-
-``` {.cpp}
-   tree->Scan("a:b:c","","colsize=30 precision=3 col=::20.10");
-```
-
-will print 3 columns, the first 2 columns will be 30 characters long,
-the third columns will be 20 characters long. The printf format for the
-columns (assuming they are numbers) will be respectively: `%30.3g`
-`%30.3g` `%20.10g`.
-
-### TEventList and TEntryList
-\index{list!event}
-\index{list!entry}
-
-The `TTree::Draw `method can also be used to build a list of the
-entries. When the first argument is preceded by `">>"` ROOT knows that
-this command is not intended to draw anything, but to save the entries
-in a list with the name given by the first argument. As a result, a
-**`TEventList`** or a **`TEntryList`** object is created in the current
-directory. For example, to create a **`TEventList`** of all entries with
-more than 600 tracks, do:
-
-``` {.cpp}
-root[] TFile *f = new TFile("Event.root");
-root[] T->Draw(">> myList","fNtrack > 600");
-```
-
-To create a **`TEntryList`**, use the option "`entrylist`".
-
-``` {.cpp}
-root[] T->Draw(">>myList", "fNtrack>600", "entrylist");
-```
-
-This list contains the entry number of all entries with more than 600
-tracks. To see the entry numbers use the `Print("all")` command.
-
-``` {.cpp}
-root[] myList->Print("all");
-```
-
-When using the "`>>`" whatever was in the list is overwritten. The list
-can be grown by using the "`>>+`" syntax. For example to add the
-entries, with exactly 600 tracks:
-
-``` {.cpp}
-root[] T->Draw(">>+ myList","fNtrack == 600", "entrylist");
-```
-
-If the `Draw` command generates duplicate entries, they are not added to
-the list.
-
-``` {.cpp}
-root[] T->Draw(">>+ myList"," fNtrack > 610", "entrylist");
-```
-
-This command does not add any new entries to the list because all
-entries with more than 610 tracks have already been found by the
-previous command for entries with more than 600 tracks.
-
-#### Main Differences between TEventList and TEntryList
-
-The functionality is essentially the same: both are used to store entry
-numbers. **`TEntryList`**, however, uses considerably less memory for
-storage, and is optimized for both very high and very low selectivity of
-cuts (see **`TEntryListBlock`** class description for the details of
-internal storage). Unlike the **`TEventList`**, **`TEntryList`** makes a
-distinction between indices from a **`TChain`** and from a **`TTree`**.
-While a **`TEntryList`** for a **`TTree`** can be seen as just a list of
-numbers, a **`TEntryList`** for a **`TChain`** is a collection of
-**`TEntryList`**(s) for the **`TTree`**(s) that constitute this
-**`TChain`**. Such "sub-lists" can be extracted by calling the function
-
-``` {.cpp}
-TEntryList::GetEntryList(const char *treename, const char *filename)
-```
-
-and then be used to construct a new **`TEntryList`** for a new
-**`TChain`**, or processed independently as normal **`TEntryList`**(s)
-for **`TTree`**(s). This modularity makes **`TEntryList`** much better
-suited for PROOF processing than the **`TEventList`**.
-
-#### Using an Event List
-
-A **`TEventList`** or a **`TEntryList`** can be used to limit the
-**`TTree`** to the events in the list. The methods `SetEventList` and
-`SetEntryList` tell the tree to use the list and hence limit all
-subsequent calls to `Draw`, `Scan`, `Process`, `Query`, `Principal` and
-`CopyTree` methods to the entries in the list. In general, it affects
-the `GetEntryNumber` method and all functions using it for looping over
-the tree entries. The `GetEntry` and `GetEntries` methods are not
-affected. Note, that in the `SetEventList` method, the **`TEventList`**
-argument is internally transformed into a **`TEntryList`**, and this
-operation, in case of a **`TChain`**, requires loading of all the tree
-headers. In this example, we create a list with all entries with more
-than 600 tracks and then set it so that the tree will use this list. To
-reset the **`TTree`** to use all events use `SetEventList(0)` or
-`SetEntryList(0)`.
-
-1. Let's look at an example. First, open the file and draw the
-`fNtrack`.
-
-``` {.cpp}
-root[] TFile *f = new TFile("Event.root");
-root[] TTree *T = (TTree*)f->Get("T");
-root[] T->Draw("fNtrack");
-```
-
-2. Now, put the entries with over 600 tracks into a **`TEntryList`**
-called `myList`. We get the list from the current directory and assign
-it to a variable list.
-
-``` {.cpp}
-root[] T->Draw(">>myList","fNtrack > 600","entrylist");
-root[] TEntryList *list=(TEntryList*)gDirectory->Get("myList");
-```
-
-3. Instruct the tree **`T`** to use the new list and draw it again. Note
-that this is exactly the same `Draw` command. The list limits the
-entries.
-
-``` {.cpp}
-root[] T->SetEntryList(list);
-root[] T->Draw("fNtrack");
-```
-
-You should now see a canvas similar to this one.
-
-![](pictures/03000105.png)
-
-#### Operations on TEntryLists
-
-If you have entry lists that were created using different cuts, you can
-combine the lists to get a new list, with entries passing at least one
-of the cuts. Example:
-
-``` {.cpp}
-root[] T->Draw(">>list1","fNtrack>600","entrylist");
-root[] TEntryList *list1 = (TEntryList*)gDirectory->Get("list1");
-root[] T->Draw(">>list2","fNtrack<590","entrylist");
-root[] TEntryList *list2 = (TEntryList*)gDirectory->Get("list2");
-root[] list1->Add(list2);
-```
-
-`list1` now contains entries with more than 600 or less than 590 tracks.
-Check this by calling:
-
-``` {.cpp}
-root[] T->SetEntryList(list1);
-root[] T->Draw("fNtrack");
-```
-
-You can also subtract **`TEntryList`** from each other, so that the
-first list contains only the entries, passing the selection of the first
-list and not present in the second list.
-
-To add some individual entries, use `TEntryList::Enter()` function. To
-remove the entries you don't like, use `TEntryList::Remove()`. To see if
-the entry is in the list, use **`TEntryList::Contains()`**. Remember, that
-all operation in a **`TEntryList`** for a **`TChain`** are on the
-**`TTree`** level. This is illustrated by the following example:
-
-``` {.cpp}
-root[] TEntryList *list1 = new TEntryList("list1","list1");
-root[] list1->SetTree("tree1","file1")
-root[] list1->Enter(0);
-root[] list1->Enter(2);
-root[] TEntryList *list2 = new TEntryList("list2", "list2");
-root[] list2->SetTree("tree2", "file2");
-root[] list2->Enter(0);
-root[] list2->Enter(3);
-root[] list1->Add(list2);
-root[] list1->Print("all")
-tree1 file1
-0
-2
-tree2 file2
-0
-3
-```
-
-The result is a **`TEntryList`** for a **`TChain`** of `tree1` and
-`tree2`. If the second list was for the same **`TTree`** in the same
-file as the first list, the result would be as follows:
-
-``` {.cpp}
-root[] TEntryList *list2_2 = new TEntryList("list2_2", "list2_2");
-root[] list2_2->SetTree("tree2", "file2");
-root[] list2_2->Enter(1);
-root[] list2_2->Enter(2);
-root[] list2->Add(list2_2);
-root[] list2->Print("all")
-tree2 file2
-0
-1
-2
-3
-```
-
-#### TEntryListFromFile
-
-This is a special kind of **`TEntryList`**, used only when processing
-**`TChain`** objects (see the method `TChain::SetEntryListFile()`). It
-is used in the case, when the entry lists, corresponding to the trees of
-this chain, are stored in separate files. It allows to load the entry
-lists in memory one by one, keeping only the list for the currently
-processed tree loaded.
-
-For more details on entry lists, see **`TEntryList`**,
-**`TEntryListBlock`** and **`TEntryListFromFile`** class descriptions,
-functions **`TChain`**`::SetEntryList()`, `TChain::SetEntryListFile()`,
-and the macro `$ROOTSYS/test/stressEntryList.C`.
-
-### Filling a Histogram
-
-
-The `TTree::Draw` method can also be used to fill a specific histogram.
-The syntax is:
-
-``` {.cpp}
-root[] TFile *f = new TFile("Event.root")
-root[] T->Draw("fNtrack >> myHisto")
-root[] myHisto->Print()
-TH1.Print Name= myHisto, Entries= 100, Total sum= 100
-```
-
-As we can see, this created a **`TH1`**, called `myHisto`. If you want
-to append more entries to the histogram, you can use this syntax:
-
-``` {.cpp}
-root[] T->Draw("fNtrack >>+ myHisto")
-```
-
-If you do not create a histogram ahead of time, ROOT will create one at
-the time of the Draw command (as is the case above). If you would like
-to draw the variable into a specific histogram where you, for example,
-set the range and bin number, you can define the histogram ahead of time
-and use it in the Draw command. The histogram has to be in the same
-directory as the tree.
-
-``` {.cpp}
-root[] TH1 *h1 = new TH1("h1","h1",50,0.,150.);
-root[] T->Draw("fNtrack>> h1");
-```
-
-When you project a **`TTree`** into a histogram, the histogram inherits
-the **`TTree`** attributes and not the current style attributes. This
-allows you to project two Trees with different attributes into the same
-picture. You can call the method `TTree::UseCurrentStyle` to change the
-histogram to use the current style ***`gStyle`***. See "Graphics and the
-Graphical User Interface.
-
-The binning of the newly created histogram can be specified in two ways.
-You can set a default in the `.rootrc` and/or you can add the binning
-information in the `TTree::Draw` command.
-
-To set number of bins default for the 1-D, 2-D, 3-D histograms can be
-specified in the `.rootrc` file via the environment variables, e.g.:
-
-```
-# default binnings   Hist.Binning.1D.x: 100
-
-Hist.Binning.2D.x: 40
-Hist.Binning.2D.y: 40
-Hist.Binning.2D.Prof: 100
-
-Hist.Binning.3D.x: 20
-Hist.Binning.3D.y: 20
-Hist.Binning.3D.z: 20
-Hist.Binning.3D.Profx: 100
-Hist.Binning.3D.Profy: 100
-```
-
-To set the number of bins for a specific histogram when using
-`TTree::Draw,` add up to nine numbers following the histogram name. The
-numbers meaning is:
-
-1 bins in x-direction
-
-2 lower limit in x-direction
-
-3 upper limit in x-direction
-
-4-6 same for y-direction
-
-7-9 same for z-direction
-
-When a bin number is specified, the value becomes the default. Any of
-the numbers can be skipped. For example:
-
-``` {.cpp}
-   tree.Draw("sqrt(x)>>hsqrt(500,10,20)";
-   // plot sqrt(x) between 10 and 20 using 500 bins
-   tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,,50,.1,.5)";
-   // plot sqrt(x) against sin(y) 100 bins in x-direction;
-   // lower limit on x-axis is 10; no upper limit
-   // 50 bins in y-direction; lower limit on y-axis is .1;
-   // upper limit is .5
-```
-
-When the name is followed by binning information, appending the
-histogram with a "+", will not reset `hsqrt`, but will continue to fill
-it.
-
-``` {.cpp}
-   tree.Draw("sqrt(x)>>+hsqrt","y>0");
-```
-
-This works for 1-D, 2-D and 3-D histograms.
-
-#### Projecting a Histogram
-
-If you would like to fill a histogram, but not draw it you can use the
-`TTree::Project()` method.
-
-``` {.cpp}
-root[] T->Project("quietHisto","fNtrack")
-```
-
-#### Making a Profile Histogram
-\index{histogram!profile}
-
-In case of a two dimensional expression, you can generate a
-**`TProfile`** histogram instead of a two dimensional histogram by
-specifying the `'prof'` or '`profs'` option. The `prof` option is
-automatically selected when the output is redirected into a
-**`TProfile`**. For example `y:x>>pf` where `pf `is an existing
-**`TProfile`** histogram.
-
-#### Tree Information
-
-Once we have drawn a tree, we can get information about the tree. These
-are the methods used to get information from a drawn tree **`TTree`**:
-
--   `GetSelectedRows`: Returns the number of entries accepted by the
-    selection expression. In case where no selection was specified, it
-    returns the number of entries processed.
-
--   `GetV1`: Returns a pointer to the float array of the first variable.
-
--   `GetV2`: Returns a pointer to the float array of second variable
-
--   `GetV3`: Returns a pointer to the float array of third variable.
-
--   `GetW`: Returns a pointer to the float array of Weights where the
-    weight equals the result of the selection expression.
-
-To read the drawn values of `fNtrack` into an array, and loop through
-the entries follow the lines below. First, open the file and draw the
-`fNtrack` variable:
-
-``` {.cpp}
-root[] TFile *f = new TFile("Event.root")
-root[] T->Draw("fNtrack")
-```
-
-Then declare a pointer to a float and use the GetV1 method to retrieve
-the first dimension of the tree. In this example we only drew one
-dimension (`fNtrack`) if we had drawn two, we could use GetV2 to get the
-second one.
-
-``` {.cpp}
-root[] Float_t *a
-root[] a = T->GetV1()
-```
-
-Loop through the first 10 entries and print the values of `fNtrack`:
-
-``` {.cpp}
-root[] for (int i = 0; i < 10; i++)
-root[] cout << a[i] << " " << endl   // need an endl to see the values
-594 597 606 595 604 610 604 602 603 596
-```
-
-By default, `TTree::Draw` creates these arrays with `fEstimate` words
-where `fEstimate` can be set via `TTree::SetEstimate`. If you have more
-entries than `fEstimate` only the first `fEstimate` selected entries
-will be stored in the arrays. The arrays are used as buffers. When
-`fEstimate` entries have been processed, ROOT scans the buffers to
-compute the minimum and maximum of each coordinate and creates the
-corresponding histograms. You can use these lines to read all entries
-into these arrays:
-
-``` {.cpp}
-root[] Int_t nestimate = (Int_t)T->GetEntries();
-root[] T->SetEstimate(nestimate);
-```
-
-Obviously, this will not work if the number of entries is very large.
-This technique is useful in several cases, for example if you want to
-draw a graph connecting all the `x`, `y(or z)` points. Note that you may
-have a tree (or chain) with 1 billion entries, but only a few may
-survive the cuts and will fit without problems in these arrays.
-
-## Using TTree::MakeClass
-\index{tree!MakeClass}
-
-The `TTree::Draw` method is convenient and easy to use; however it falls
-short if you need to do some programming with the variable.
-
-For example, for plotting the masses of all oppositely changed pairs of
-tracks, you would need to write a program that loops over all events,
-finds all pairs of tracks, and calculates the required quantities. We
-have shown how to retrieve the data arrays from the branches of the tree
-in the previous section, and you could just write that program from
-scratch. Since this is a very common task, ROOT provides a utility that
-generates a skeleton class designed to loop over the entries of the
-tree.
-
-This is the `TTree::MakeClass` method. We will now go through the steps
-of using `MakeClass` with a simplified example. The methods used here
-obviously work for complex event loop calculations.
-
-These are our assumptions: we would like to do selective plotting and
-loop through each entry of the tree and tracks. We chose a simple
-example: we want to plot `fPx` of the first 100 tracks of each entry. We
-have a ROOT tree with a branch for each data member in the "`Event`"
-object. To build this file and tree follow the instructions on how to
-build the examples in `$ROOTSYS/test`. Execute `Event` and instruct it
-to split the object with this command (from the UNIX command line).
-
-``` {.cpp}
-> $ROOTSYS/test/Event 400 1 2 1
-```
-
-This creates an `Event.root` file with 400 events, compressed, split,
-and filled.
-
-See `$ROOTSYS/test/MainEvent.cxx` for more info.
-
-The person who designed the tree makes a shared library available to
-you, which defines the classes needed. In this case, the classes are
-Event, `EventHeader`, and Track and they are defined in the shared
-library `libEvent.so`. The designer also gives you the `Event.h` file to
-see the definition of the classes. You can locate `Event.h` in
-`$ROOTSYS/test`, and if you have not yet built `libEvent.so`, please see
-the instructions of how to build it (typing make in \$ROOTSYS/test is
-enough). If you have already built it, you can now use it again.
-
-### Creating a Class with MakeClass
-
-
-First, we load the shared library and open `Event.root`.
-
-``` {.cpp}
-root[] .L libEvent.so
-root[] TFile *f = new TFile("Event.root");
-root[] f->ls();
-TFile**         Event.root      TTree benchmark ROOT file
-TFile*         Event.root      TTree benchmark ROOT file
-KEY: TH1F     htime;1 Real-Time to write versus time
-KEY: TTree    T;1     An example of a ROOT tree
-```
-
-We can see there is a tree "`T`", and just to verify that we are working
-with the correct one, we print the tree, which will show us the header
-and branches.
-
-``` {.cpp}
-root[] T->Print();
-```
-
-From the output of print we can see that the tree has one branch for
-each data member of `Event`, `Track`, and `EventHeader`. Now we can use
-`TTree::MakeClass` on our tree "`T`". `MakeClass` takes one parameter, a
-string containing the name of the class to be made. In the command
-below, the name of our class will be "`MyClass`".
-
-``` {.cpp}
-root[] T->MakeClass("MyClass")
-Files: MyClass.h and MyClass.C generated from Tree: T
-```
-
-(Warning: it's recommended to use `MakeSelector` or `MakeProxy`
-rather than `MakeClass`.)
-
-The routine informs us that it has created two files. `MyClass.h` contains the
-class definition and `MyClass.C` contains the `MyClass::Loop()` method.
-`MyClass` has more methods than just `Loop()`. The other methods are a
-constructor, a destructor, `GetEntry()`, `LoadTree()`, `Notify()`,
-`Cut()` and `Show()`. The implementations of these methods are in the .h
-file. This division of methods was done intentionally. The `.C` file is
-kept as short as possible, and contains only code that is intended for
-you to customize. The `.h` file contains all the other methods. It is
-clear that you want to be as independent as possible of the header file
-(i.e. `MyClass.h`) generated by `MakeClass`. The solution is to
-implement a derived class, for example `MyRealClass` deriving from
-`MyClass` such that a change in your `Tree` or regeneration of
-`MyClass.h` does not force you to change `MyRealClass.h`. In other words,
-imagine that you have called `MakeClass`, and then spent an hour modifying
-a custom implementation of the file `MyClass.C` with your algorithm. Now,
-you decided to change the name of your variables in your original class/tree,
-and recall `MakeClass` to update the auto-generated files. If you didn't
-backup your custom code, it will be lost and you will have to redo the work.
-So the workaround is to create a separate file `MyRealClass.h` containing
-`class MyRealClass : public MyClass` declaration that overrides the 
-custom functions (instead of editing `MyClass.C` for customization, you edit
-`MyRealClass.cpp`). That way, whenever you decide to change
-your class and recall `MakeClass`, your changes will be spared from overwriting
-and you will just need to adapt/edit the code in `MyRealClass.cpp`.
-You can imagine deriving several classes from `MyClass.h`, each with a specific
-algorithm. To understand both files, let's start with `MyClass.h` and
-the class declaration:
-
-### MyClass.h
-
-
-``` {.cpp}
-class MyClass {
-   public :
-      // Pointer to the analyzed TTree or TChain
-      TTree          *fChain;
-      // Current Tree number in a TChain
-      Int_t           fCurrent;
-      // Declaration of leaves types
-      UInt_t          fUniqueID;
-      UInt_t          fBits;
-      Char_t          fType[20];
-      Int_t           fNtrack;
-      Int_t           fNseg;
-      Int_t           fNvertex;
-      UInt_t          fFlag;
-      Float_t         fTemperature;
-      Int_t           fEvtHdr_fEvtNum;
-      // List of branches
-      TBranch        *b_fUniqueID;
-      TBranch        *b_fBits;
-      TBranch        *b_fType;
-      TBranch        *b_fNtrack;
-      TBranch        *b_fNseg;
-      TBranch        *b_fNvertex;
-      TBranch        *b_fFlag;
-      TBranch        *b_fTemperature;
-      TBranch        *b_fEvtHdr_fEvtNum;
-...
-             MyClass(TTree *tree=0);
-            ~MyClass();
-      Int_t  Cut(Int_t entry);
-      Int_t  GetEntry(Int_t entry);
-      Int_t  LoadTree(Int_t entry);
-      void   Init(TTree *tree);
-      void   Loop();
-      Bool_t Notify();
-      void   Show(Int_t entry = -1);
-};
-```
-
-We can see data members in the generated class. The first data member is
-`fChain`. Once this class is instantiated, `fChain` will point to the
-original tree or chain this class was made from. In our case, this is
-"T" in "`Event.root`". If the class is instantiated with a tree as a
-parameter to the constructor, `fChain` will point to the tree named in
-the parameter. Next is `fCurrent`, which is also a pointer to the
-current tree/chain. Its role is only relevant when we have multiple
-trees chained together in a **`TChain`**. The class definition shows us
-that this tree has one branch and one leaf per data member. The methods
-of `MyClass` are:
-
--   `MyClass(TTree *tree=0) -` this constructor has an optional tree
-    for a parameter. If you pass a tree, `MyClass` will use it rather
-    than the tree from which it was created.
-
--   `void  Init(TTree *tree) -` it is called by the constructor to
-    initialize the tree for reading. It associates each branch with the
-    corresponding leaf data member.
-
--   `~MyClass() - `the destructor, nothing special.
-
--   `Int_t GetEntry(Int_t entry) -` it loads the class with the entry
-    specified. Once you have executed `GetEntry`, the leaf data members
-    in `MyClass` are set to the values of the entry. For example,
-    `GetEntry(12)` loads the 13th event into the event data member of
-    `MyClass` (note that the first entry is 0). `GetEntry` returns the
-    number of bytes read from the file. In case the same entry is read
-    twice, ROOT does not have to do any I/O. In this case `GetEntry`
-    returns 1. It does not return 0, because many people assume a return
-    of 0 means an error has occurred while reading.
-
--   `Int_t LoadTree(Int_t entry)` and `void  Notify()` - these two
-    methods are related to chains. `LoadTree` will load the tree
-    containing the specified entry from a chain of trees. Notify is
-    called by `LoadTree` to adjust the branch addresses.
-
--   `void Loop()` - it is the skeleton method that loops through each
-    entry of the tree. This is interesting to us, because we will need
-    to customize it for our analysis.
-
-### MyClass.C
-
-
-`MyClass::Loop` consists of a for-loop calling `GetEntry` for each
-entry. In the template, the numbers of bytes are added up, but it does
-nothing else. If we were to execute it now, there would be no output.
-
-``` {.cpp}
-void MyClass::Loop() {
-   if (fChain == 0) return;
-
-   Int_t nentries = Int_t(fChain->GetEntries());
-   Int_t nbytes = 0, nb = 0;
-   for (Int_t jentry=0; jentry<nentries;jentry++) {
-      Int_t ientry = LoadTree(jentry);
-      // in case of a TChain   , ientry is the entry number in the
-      // current file
-      nb = fChain->GetEntry(jentry);   nbytes += nb;
-      // if (Cut(ientry) < 0) continue;
-   }
-}
-```
-
-At the beginning of the file are instructions about reading selected
-branches. They are not reprinted here, but please read them from your
-own file
-
-### Modifying MyClass::Loop
-
-
-Let us continue with the goal of going through the first 100 tracks of
-each entry and plot `Px`. To do this we change the Loop method.
-
-``` {.cpp}
-...
-   if (fChain == 0) return;
-   Int_t nentries = Int_t(fChain->GetEntries());
-   TH1F *myHisto  = new TH1F("myHisto","fPx", 100, -5,5);
-   TH1F *smallHisto = new TH1F("small","fPx", 100, -5,5);
-...
-```
-
-In the for-loop, we need to add another for-loop to go over all the
-tracks. In the outer for-loop, we get the entry and the number of
-tracks. In the inner for-loop, we fill the large histogram (`myHisto`)
-with all tracks and the small histogram (`smallHisto`) with the track if
-it is in the first 100.
-
-``` {.cpp}
-...
-   for (Int_t jentry=0; jentry<nentries;jentry++) {
-      GetEntry(jentry);
-      for (Int_t j = 0; j < 100; j++) {
-         myHisto->Fill(fTracks_fPx[j]);
-         if (j < 100) {
-            smallHisto->Fill(fTracks_fPx[j]);
-         }
-      }
-   }
-...
-```
-
-Outside of the for-loop, we draw both histograms on the same canvas.
-
-``` {.cpp}
-...
-   myHisto->Draw();
-   smallHisto->Draw("Same");
-...
-```
-
-Save these changes to `MyClass.C` and start a fresh root session. We
-will now load `MyClass` and experiment with its methods.
-
-### Loading MyClass
-
-
-The first step is to load the library and the class file. Then we can
-instantiate a `MyClass` object.
-
-``` {.cpp}
-root[] .L libEvent.so
-root[] .L MyClass.C
-root[] MyClass m
-```
-
-Now we can get a specific entry and populate the event leaf. In the code
-snipped below, we get entry 0, and print the number of tracks (594).
-Then we get entry 1 and print the number of tracks (597).
-
-``` {.cpp}
-root[] m.GetEntry(0)
-(int)57503
-root[] m.fNtrack()
-(Int_t)594
-root[] m.GetEntry(1)
-(int)48045
-root[] m.fNtrack()
-(Int_t)597
-```
-
-Now we can call the `Loop` method, which will build and display the two
-histograms.
-
-``` {.cpp}
-root[] m.Loop()
-```
-
-You should now see a canvas that looks like this.
-
-![](pictures/03000106.png)
-
-To conclude the discussion on `MakeClass` let us lists the steps that
-got us here.
-
--   Call `TTree::MakeClass`, which automatically creates a class to loop
-    over the tree.
-
--   Modify the `MyClass::Loop()` method in `MyClass.C` to fit your task.
-
--   Load and instantiate `MyClass`, and run `MyClass::Loop()`.
-
-## Using TTree::MakeSelector
-\index{tree!MakeSelector}
-
-With a **`TTree`** we can make a selector and use it to process a
-limited set of entries. This is especially important in a parallel
-processing configuration where the analysis is distributed over several
-processors and we can specify which entries to send to each processor.
-The `TTree::Process` method is used to specify the selector and the
-entries. Before we can use **`TTree::Process`** we need to make a
-selector. We can call the `TTree::MakeSelector` method. It creates
-two files similar to `TTree::MakeClass`.
-
-In the resulting files is a class that is a descendent of
-**`TSelector`** and implements the following methods:
-
--   `TSelector::Begin()` `-` this method is called every time a loop
-    over the tree starts. This is a convenient place to create your
-    histograms.
-
--   `TSelector::Notify()` `-` it is called at the first entry of a new
-    tree in a chain.
-
--   `TSelector::Process()` `-` it is called to process an event. It is
-    the user's responsibility to read the corresponding entry in memory
-    (may be just a partial read). Once the entry is in memory one can
-    apply a selection and if the event is selected histograms can be
-    filled. Processing stops when this function returns `kFALSE`. It
-    combines the methods **`TSelector::ProcessCut()` and
-    `TSelector`**`::ProcessFill()` in one, avoiding the necessity to
-    maintain the state in the class to communicate between these two
-    functions. It reduces the information that needs to be shared
-    between them and promotes a more granular data access by reading
-    branches as they are needed.
-
--   `TSelector::Terminate() -` it is called at the end of a loop on a
-    **`TTree`**. This is a convenient place to draw and fit your
-    histograms.
-
--   `TSelector::Version()` `-` this function provides backward
-    compatibility for old versions and support for the future upgrades.
-
--   The **`TSelector`**, unlike the resulting class from `MakeClass`,
-    separates the processing into a `ProcessCut()` and `ProcessFill()`,
-    so we can limit reading of branches to the ones we need.
-
--   When a selector is used with a **`TChain`** in methods `Process()`,
-    `ProcessFill()`, `ProcessCut()`, you must use the pointer to the
-    current **`TTree`** to call the method `GetEntry(entry)`. The
-    parameter `entry` is always the local entry number in the current
-    tree. Assuming that `fChain` is the pointer to the **`TChain`**
-    being processed, use
-
-``` {.cpp}
-   fChain->GetTree()->GetEntry(entry);
-```
-
-To create a selector call:
-
-``` {.cpp}
-root[] T->MakeSelector("MySelector");
-```
-
-Where `T` is the **`TTree`** and `MySelector` is the name of created
-class and the name of the `.h` and `.C` files. The resulting
-**`TSelector`** is the argument to **`TTree::Process`**. The argument can
-be the file name or a pointer to the selector object.
-
-``` {.cpp}
-root[] T->Process("MySelector.C","",1000,100);
-```
-
-This call will interpret the class defined in `MySelector.C` and process
-1000 entries beginning with entry 100. The file name can be appended
-with a "+" or a "++" to use `ACLiC`.
-
-``` {.cpp}
-root[] T->Process("MySelector.C++","",1000,100);
-```
-
-When appending a "++", the class will be compiled and dynamically
-loaded.
-
-``` {.cpp}
-root[] T->Process("MySelector.C+","",1000,100);
-```
-
-When appending a "+", the class will also be compiled and dynamically
-loaded. When it is called again, it recompiles only if the macro
-(`MySelector.C`) has changed since it was compiled last. If not, it
-loads the existing library. The next example shows how to create a
-selector with a pointer:
-
-``` {.cpp}
-MySelector *selector = (MySelector *)TSelector::GetSelector("MySelector.C+");
-T->Process(selector);
-```
-
-`Using this form, you can do things like:`
-
-``` {.cpp}
-   selector->public_attribute1 = init_value;
-   for (int i=0; i<limit; i++) {
-      T->Process(selector);
-      selector->public_attribute1 =
-         function(selector->public_attribute2);
-   }
-```
-
-`TTree::Process()` is aware of PROOF, ROOT parallel processing facility.
-If PROOF is setup, it divides the processing amongst the slave CPUs.
-
-### Performance Benchmarks
-\index{benchmarks}
-
-The program `$ROOTSYS/test/bench.cxx` compares the I/O performance of
-STL vectors to the ROOT native **`TClonesArray`**`s` collection class.
-It creates trees with and without compression for the following cases:
-`vector<THit>`, `vector<THit*>`, `TClonesArray(`**`TObjHit`**`)`
-not split `TClonesArray(`**`TObjHit`**`)` split.
-
-The next graphs show the two columns on the right which represent the split and
-non-split **`TClonesArray`**, are significantly lower than the vectors. The most
-significant difference is in reading a file without compression.
-
-The file size with compression, write times with and without compression
-and the read times with and without compression all favor the
-**`TClonesArray`**.
-
-## Impact of Compression on I/O
-
-
-This benchmark illustrates the pros and cons of the compression option.
-We recommend using compression when the time spent in I/O is small
-compared to the total processing time. In this case, if the I/O
-operation is increased by a factor of 5 it is still a small percentage
-of the total time and it may very well save a factor of 10 on disk
-space. On the other hand if the time spend on I/O is large, compression
-may slow down the program's performance. The standard test program
-`$ROOTSYS/test/Event` was used in various configurations with 400
-events. The data file contains a **`TTree`**. The program was invoked
-with:
-
-``` {.cpp}
-Event 400 comp split
-```
-
--   comp = 0 means: no compression at all.
--   comp = 1 means: compress everything if split = 0.
--   comp = 1 means: compress only the tree branches with integers if
-    split = 1.
--   comp = 2 means: compress everything if split=1.
--   split = 0 : the full event is serialized into one single buffer.
--   split = 1 : the event is split into branches. One branch for each
-    data member of the Event class. The list of tracks (a
-    **`TClonesArray`**) has the data members of the Track class also
-    split into individual buffers.
-
-These tests were run on Pentium III CPU with 650 MHz.
-
-+------------+--------+---------------+---------------+----------------+----------------+
-| Event      | File   | Total Time to | Effective     | Total Time to  | Total Time to  |
-| Parameters | Size   | Write         | Time to Write | Read All       | Read Sample    |
-|            |        | (MB/sec)      | (MB/sec)      | (MB/sec)       | (MB/sec)       |
-+------------+--------+---------------+---------------+----------------+----------------+
-| Comp = 0   | 19.75  | 6.84 s.(2.8   | 3.56 s.(5.4   | 0.79s.(24.2    | 0.79 s.(24.2   |
-|            | MB     | MB/s)         | MB/s)         | MB/s)          | MB/s)          |
-| Split = 1  |        |               |               |                |                |
-+------------+--------+---------------+---------------+----------------+----------------+
-| Comp = 1   | 17.73  | 6.44 s.(3.0   | 4.02 s.(4.8   | 0.90 s.(21.3   | 0.90 s.(21.3   |
-|            | MB     | MB/s)         | MB/s)         | MB/s)          | MB/s)          |
-| Split = 1  |        |               |               |                |                |
-+------------+--------+---------------+---------------+----------------+----------------+
-| Comp = 2   | 13.78  | 11.34s.(1.7   | 9.51 s.(2.0   | 2.17 s.(8.8    | 2.17 s.(8.8    |
-|            | MB     | MB/s)         | MB/s)         | MB/s)          | MB/s)          |
-| Split = 1  |        |               |               |                |                |
-+------------+--------+---------------+---------------+----------------+----------------+
-
-The **Total Time** is the real time in seconds to run the program.
-**Effective time** is the real time minus the time spent in non I/O
-operations (essentially the random number generator). The program
-`Event` generates in average 600 tracks per event. Each track has 17
-data members. The read benchmark runs in the interactive version of
-ROOT. The ‘Total Time to Read All' is the real time reported by the
-execution of the script `&ROOTSYS/test/eventa`.
-
-We did not correct this time for the overhead coming from the
-interpreter itself. The **Total time to read sample** is the execution
-time of the script `$ROOTSYS/test/eventb`. This script loops on all
-events. For each event, the branch containing the number of tracks is
-read. In case the number of tracks is less than 585, the full event is
-read in memory. This test is obviously not possible in non-split mode.
-In non-split mode, the full event must be read in memory. The times
-reported in the table correspond to complete I/O operations necessary to
-deal with **machine independent binary files**. On **Linux**, this also
-includes byte-swapping operations. The ROOT file allows for direct
-access to any event in the file and direct access to any part of an
-event when split=1.
-
-Note also that the uncompressed file generated with split=0 is 48.7
-Mbytes and only 47.17 Mbytes for the option split=1. The difference in
-size is due to the object identification mechanism overhead when the
-event is written to a single buffer. This overhead does not exist in
-split mode because the branch buffers are optimized for homogeneous data
-types. You can run the test programs on your architecture. The program
-`Event` will report the write performance. You can measure the read
-performance by executing the scripts `eventa` and `eventb`. The
-performance depends not only of the processor type, but also of the disk
-devices (local, NFS, AFS, etc.).
-
-## Chains
-\index{tree!chains}
-
-A **`TChain`** object is a list of ROOT files containing the same tree.
-As an example, assume we have three files called
-`file1.root, file2.root, file3.root`. Each file contains one tree called
-"`T`". We can create a chain with the following statements:
-
-``` {.cpp}
-   TChain chain("T");   // name of the tree is the argument
-   chain.Add("file1.root");
-   chain.Add("file2.root");
-   chain.Add("file3.root");
-```
-
-The name of the **`TChain`** will be the same as the name of the tree;
-in this case it will be `"T". Note that two `objects can have the same
-name as long as they are not histograms in the same directory, because
-there, the histogram names are used to build a hash table. The class
-**`TChain`** is derived from the class **`TTree`**. For example, to
-generate a histogram corresponding to the attribute "`x`" in tree "`T`"
-by processing sequentially the three files of this chain, we can use the
-`TChain::Draw` method.
-
-``` {.cpp}
-   chain.Draw("x");
-```
-
-When using a **`TChain`**, the branch address(es) must be set with:
-
-``` {.cpp}
-   chain.SetBranchAdress(branchname,...)  // use this for TChain
-```
-
-rather than:
-
-``` {.cpp}
-   branch->SetAddress(...);  // this will not work
-```
-
-The second form returns the pointer to the branch of the current
-**`TTree`** in the chain, typically the first one. The information is
-lost when the next **`TTree`** is loaded. The following statements
-illustrate how to set the address of the object to be read and how to
-loop on all events of all files of the chain.
-
-``` {.cpp}
-{
-   TChain chain("T"); // create the chain with tree "T"
-   chain.Add("file1.root"); // add the files
-   chain.Add("file2.root");
-   chain.Add("file3.root");
-   TH1F *hnseg = new TH1F("hnseg",
-                          "Number of segments for selected tracks",
-                          5000,0,5000);
-   // create an object before setting the branch address
-   Event *event = new Event();
-   // Specify the address where to read the event object
-   chain.SetBranchAddress("event", &event);
-
-   // Start main loop on all events In case you want to read only a few
-   // branches, use TChain::SetBranchStatus to activate a branch.
-   Int_t nevent = chain.GetEntries();
-   for (Int_t i=0;i<nevent;i++) {
-      // read complete accepted event in memory
-      chain.GetEvent(i);
-      // Fill histogram with number of segments
-      hnseg->Fill(event->GetNseg());
-   }
-   // Draw the histogram
-   hnseg->Draw();
-}
-```
-
-### TChain::AddFriend
-\index{tree!friend}
-
-`A `**`TChain`** has a list of friends similar to a tree (see
-`TTree::AddFriend)`. You can add a friend to a chain with the
-`TChain::AddFriend` method. With `TChain::GetListOfFriends` you can
-retrieve the list of friends. The next example has four chains each has
-20 ROOT trees from 20 ROOT files.
-
-``` {.cpp}
-   TChain ch("t");    // a chain with 20 trees from 20 files
-   TChain ch1("t1");
-   TChain ch2("t2");
-   TChain ch3("t3");
-```
-
-Now we can add the friends to the first chain.
-
-``` {.cpp}
-   ch.AddFriend("t1");
-   ch.AddFriend("t2");
-   ch.AddFriend("t3");
-```
-
-The parameter is the name of friend chain (the name of a chain is always
-the name of the tree from which it was created). The original chain has
-access to all variables in its friends. We can use the `TChain::Draw`
-method as if the values in the friends were in the original chain. To
-specify the chain to use in the `Draw` method, use:
-
-``` {.cpp}
-<chainname>.<branchname>.<varname>
-```
-
-If the variable name is enough to identify uniquely the variable, you
-can leave out the chain and/or branch name. For example, this generates
-a 3-d scatter plot of variable "`var`" in the `TChain ch` versus
-variable `v1 in `**`TChain t1` versus variable `v2` in `TChain`**` t2`.
-
-``` {.cpp}
-   ch.Draw("var:t1.v1:t2.v2");
-```
-
-When a `TChain::Draw` is executed, an automatic call to
-`TTree::AddFriend `connects the trees in the chain. When a chain
-is deleted, its friend elements are also deleted.
-
-![](pictures/02000108.jpg)
-
-The number of entries in the friend must be equal or greater to the
-number of entries of the original chain. If the friend has fewer entries
-a warning is given and the resulting histogram will have missing
-entries. For additional information see `TTree::AddFriends()`. A full
-example of a tree and friends is in Example \#3
-`($ROOTSYS/tutorials/io/tree/tree107_tree.C`) in the Trees section above.
diff --git a/documentation/users-guide/TutorialsandTests.md b/documentation/users-guide/TutorialsandTests.md
deleted file mode 100644
index de0eb834883f9..0000000000000
--- a/documentation/users-guide/TutorialsandTests.md
+++ /dev/null
@@ -1,433 +0,0 @@
-# The Tutorials and Tests
-
-
-This chapter is a guide to the examples that come with the installation
-of ROOT. They are located in two directories: `$ROOTSYS/tutorials` and
-`$ROOTSYS/test`.
-
-## \$ROOTSYS/tutorials
-
-
-![](pictures/030001F9.png)
-
-The tutorials directory contains many example
-scripts. *To have all examples working you must have write permission
-and you will need to execute`hsimple.C` first*. If you do not have write
-permission in the directory` $ROOTSYS/tutorials`, copy the entire
-directory to your area. The script `hsimple.C` displays a histogram as
-it is being filled, and creates a ROOT file used by the other examples.
-
-To execute it type:
-
-``` {.cpp}
-$ cd $ROOTSYS/tutorials
-$ root
-   -------------------------------------------------------------------------
-  | Welcome to ROOT 6.10/01                             http://root.cern.ch |
-  |                                            (c) 1995-2017, The ROOT Team |
-  | Built for macosx64                                                      |
-  | From heads/v6-10-00-patches@v6-10-00-25-g9f78c3a, Jul 03 2017, 11:39:44 |
-  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'              |
-   -------------------------------------------------------------------------
-
-root [0] .x hsimple.C
-```
-
-Now execute `demos.C`, which brings up the button bar shown on the left.
-You can click on any button to execute another example. To see the
-source, open the corresponding source file (for example `fit1.C`). Once
-you are done, and want to quit the ROOT session, you can do so by typing
-**`.q`**.
-
-``` {.cpp}
-root[] .x demos.C
-root[] .q
-```
-
-## \$ROOTSYS/test
-
-
-The test directory contains a set of examples that represent all areas
-of the framework. When a new release is cut, the examples in this
-directory are compiled and run to test the new release's backward
-compatibility.
-
-We see these source files:
-
-+-------------------+--------------------------------------------------------+
-| `Makefile`        | Makefile to build all test programs.                   |
-+-------------------+--------------------------------------------------------+
-| `hsimple.cxx`     | Simple test program that creates and saves some        |
-|                   | histograms                                             |
-+-------------------+--------------------------------------------------------+
-| `MainEvent.cxx`   | Simple test program that creates a ROOT Tree object    |
-|                   | and fills it with some simple structures but also with |
-|                   | complete histograms. This program uses the files       |
-|                   | `Event.cxx`, `EventCint.cxx` and `Event.h`. An example |
-|                   | of a procedure to link this program is in              |
-|                   | `bind_Event`. Note that the `Makefile` invokes the     |
-|                   | `rootcling` utility to generate the Cling interface      |
-|                   | `EventCint.cxx`                                        |
-+-------------------+--------------------------------------------------------+
-| `Event.cxx`       | Implementation for classes Event and Track             |
-+-------------------+--------------------------------------------------------+
-| `minexam.cxx`     | Simple test program for data fitting                   |
-+-------------------+--------------------------------------------------------+
-| `tcollex.cxx`     | Example usage of the ROOT collection classes           |
-+-------------------+--------------------------------------------------------+
-| `tcollbm.cxx`     | Benchmarks of ROOT collection classes                  |
-+-------------------+--------------------------------------------------------+
-| ctorture.cxx      | Test program for the class **`TComplex`**              |
-+-------------------+--------------------------------------------------------+
-| `tstring.cxx`     | Example usage of the ROOT string class                 |
-+-------------------+--------------------------------------------------------+
-| `vmatrix.cxx`     | Verification program for the **`TMatrix`** class       |
-+-------------------+--------------------------------------------------------+
-| `vvector.cxx`     | Verification program for the **`TVector `**class       |
-+-------------------+--------------------------------------------------------+
-| `vlazy.cxx`       | Verification program for lazy matrices                 |
-+-------------------+--------------------------------------------------------+
-| `hworld.cxx`      | Small program showing basic graphics                   |
-+-------------------+--------------------------------------------------------+
-| `guitest.cxx`     | Example usage of the ROOT GUI classes                  |
-+-------------------+--------------------------------------------------------+
-| `gui` `viewer`    | Another ROOT GUI example program                       |
-| `.cxx`            |                                                        |
-+-------------------+--------------------------------------------------------+
-| `Hello.cxx`       | Dancing text example                                   |
-+-------------------+--------------------------------------------------------+
-| `Aclock.cxx`      | Analog clock (a la X11 `xclock`)                       |
-+-------------------+--------------------------------------------------------+
-| `Tetris.cxx`      | The known Tetris game based on the ROOT graphics       |
-+-------------------+--------------------------------------------------------+
-| `stress.cxx`      | Important ROOT stress testing program                  |
-+-------------------+--------------------------------------------------------+
-| `stress*.cxx`     | Stress testing of different ROOT classes               |
-+-------------------+--------------------------------------------------------+
-| `bench.cxx`       | STL and ROOT container test and benchmarking program   |
-+-------------------+--------------------------------------------------------+
-| QpRandomDriver.cx | Verification program for Quadratic programming classes |
-| x                 | in Quadp library                                       |
-+-------------------+--------------------------------------------------------+
-| DrawTest.sh       | Entry script to extensive **`TTree`** query test suite |
-+-------------------+--------------------------------------------------------+
-| dt\_\*            | Scripts used by DrawTest.sh                            |
-+-------------------+--------------------------------------------------------+
-
-The `$ROOTSYS/test` directory is a gold mine of root-wisdom nuggets, and
-we encourage you to explore and exploit it. These instructions will
-compile all programs in `$ROOTSYS/test`:
-
-If you do not have write permission in the `$ROOTSYS/test` directory,
-copy the entire `$ROOTSYS/test` directory to your area. The `Makefile`
-is a useful example of how ROOT applications are linked and built. Edit
-the `Makefile` to specify your architecture by changing the `ARCH`
-variable, for example, on an SGI machine type:` ARCH` = `sgikcc`.
-
-Now compile all programs:
-
-% **`gmake`**
-
-This will build several applications and shared libraries. We are
-especially interested in Event, stress, and `guitest`.
-
-### Event - An Example of a ROOT Application
-
-
-Event is created by compiling `MainEvent.cxx`, and `Event.cxx`. It
-creates a ROOT file with a tree and two histograms. When running `Event`
-we have four optional arguments with defaults:
-
-+-----+---------------------------------------------------------+--------------+
-|     | Argument                                                | Default      |
-+-----+---------------------------------------------------------+--------------+
-| 1   | Number of Events (1 ... n)                              | 400          |
-+-----+---------------------------------------------------------+--------------+
-| 2   | Compression level:                                      | 1            |
-|     |                                                         |              |
-|     | 0: no compression at all.                               |              |
-|     |                                                         |              |
-|     | 1: If the split level is set to zero, everything is     |              |
-|     | compressed according to the `gzip` level 1. If split    |              |
-|     | level is set to 1, leaves that are not floating point   |              |
-|     | numbers are compressed using the `gzip` level 1.        |              |
-|     |                                                         |              |
-|     | 2: If the split level is set to zero, everything is     |              |
-|     | compressed according to the `gzip` level 2. If split    |              |
-|     | level is set to 1, all non floating point leaves are    |              |
-|     | compressed according to the `gzip` level 2 and the      |              |
-|     | floating point leaves are compressed according to the   |              |
-|     | `gzip` level 1 (`gzip` level -1).                       |              |
-|     |                                                         |              |
-|     | Floating point numbers are compressed differently       |              |
-|     | because the gain when compressing them is about 20 -    |              |
-|     | 30%. For other data types it is generally better and    |              |
-|     | around 100%.                                            |              |
-+-----+---------------------------------------------------------+--------------+
-| 3   | Split or not Split                                      | 1            |
-|     |                                                         |              |
-|     | 0: only one single branch is created and the complete   | (Split)      |
-|     | event is serialized in one single buffer                |              |
-|     |                                                         |              |
-|     | 1: a branch per variable is created.                    |              |
-+-----+---------------------------------------------------------+--------------+
-| 4   | Fill                                                    | 1            |
-|     |                                                         |              |
-|     | 0: read the file                                        | (Write, no   |
-|     |                                                         | fill)        |
-|     | 1: write the file, but don't fill the histograms        |              |
-|     |                                                         |              |
-|     | 2: don't write, don't fill the histograms               |              |
-|     |                                                         |              |
-|     | 10: fill the histograms, don't write the file           |              |
-|     |                                                         |              |
-|     | 11: fill the histograms, write the file                 |              |
-|     |                                                         |              |
-|     | 20: read the file sequentially                          |              |
-|     |                                                         |              |
-|     | 25: read the file at random                             |              |
-+-----+---------------------------------------------------------+--------------+
-
-#### Effect of Compression on File Size and Write Times
-
-You may have noticed that a ROOT file has up to nine compression level,
-but here only levels 0, 1, and 2 are described. Compression levels above
-2 are not competitive. They take up to much write time compared to the
-gain in file space. Below are three runs of `Event` on a Pentium III 650
-MHz and the resulting file size and write and read times.
-
-No Compression:
-
-``` {.cpp}
-> Event 400 0 1 1
-400 events and 19153182 bytes processed.
-RealTime=6.840000 seconds, CpuTime=3.560000 seconds
-compression level=0, split=1, arg4=1
-You write 2.800173 Mbytes/Realtime seconds
-You write 5.380107 Mbytes/Cputime seconds
-
-> ls -l Event.root
-... 19752171 Feb 23 18:26 Event.root
-
-> Event 400 0 1 20
-400 events and 19153182 bytes processed.
-RealTime=0.790000 seconds, CpuTime=0.790000 seconds
-You read 24.244533 Mbytes/Realtime seconds
-You read 24.244533 Mbytes/Cputime seconds
-```
-
-We see the file size without compression is 19.75 MB, the write time is
-6.84 seconds and the read time is 0.79 seconds.
-
-Compression = 1: event is compressed:
-
-``` {.cpp}
-> Event 400 1 1 1
-400 events and 19153182 bytes processed.
-RealTime=6.440000 seconds, CpuTime=4.020000 seconds
-compression level=1, split=1, arg4=1
-You write 2.974096 Mbytes/Realtime seconds
-You write 4.764473 Mbytes/Cputime seconds
-
-> ls -l Event.root
-...     17728188 Feb 23 18:28 Event.root
-
-> Event 400 1 1 20
-400 events and 19153182 bytes processed.
-RealTime=0.900000 seconds, CpuTime=0.900000 seconds
-You read 21.281312 Mbytes/Realtime seconds
-You read 21.281312 Mbytes/Cputime seconds
-```
-
-We see the file size 17.73, the write time was 6.44 seconds and the read
-time was 0.9 seconds.
-
-Compression = 2: Floating point numbers are compressed with level 1:
-
-``` {.cpp}
-> Event 400 2 1 1
-400 events and 19153182 bytes processed.
-RealTime=11.340000 seconds, CpuTime=9.510000 seconds
-compression level=2, split=1, arg4=1
-You write 1.688993 Mbytes/Realtime seconds
-You write 2.014004 Mbytes/Cputime seconds
-
-> ls -l Event.root
-...     13783799 Feb 23 18:29 Event.root
-
-> Event 400 2 1 20
-400 events and 19153182 bytes processed.
-RealTime=2.170000 seconds, CpuTime=2.170000 seconds
-You read 8.826351 Mbytes/Realtime seconds
-You read 8.826351 Mbytes/Cputime seconds
-```
-
-The file size is 13.78 MB, the write time is 11.34 seconds and the read
-time is 2.17 seconds.
-
-This table summarizes the findings on the impact of compressions:
-
-+---------------------+----------------------+-------------------+---------------+
-| Compression         | File Size            | Write Times       | Read Times    |
-+---------------------+----------------------+-------------------+---------------+
-| 0                   | 19.75 MB             | 6.84 sec.         | 0.79 sec.     |
-+---------------------+----------------------+-------------------+---------------+
-| 1                   | 17.73 MB             | 6.44 sec.         | 0.90 sec.     |
-+---------------------+----------------------+-------------------+---------------+
-| 2                   | 13.78 MB             | 11.34 sec.        | 2.17 sec.     |
-+---------------------+----------------------+-------------------+---------------+
-
-#### Setting the Split Level
-
-![](pictures/080001FA.png)
-
-Split Level = 0: \
-Now we execute Event with the split parameter set to 0:
-
-``` {.cpp}
-> Event 400 1 0 1
-> root
-root[] TFile f("Event.root")
-root[] TBrowser T
-```
-
-We notice that only one branch is visible (event). The individual data
-members of the `Event` object are no longer visible in the browser. They
-are contained in the event object on the event branch, because we
-specified no splitting. Split Level = 1:
-
-Setting the split level to 1 will create a branch for each data member
-in the Event object. First we execute `Event` and set the split level to
-1 and start the browser to examine the split tree:
-
-``` {.cpp}
->     Event 400 1 1 1
-```
-
-``` {.cpp}
->     root
-root[] TFile f("Event.root")
-root[] TBrowser browser
-```
-
-![](pictures/080001FB.png)
-
-### stress - Test and Benchmark
-
-
-The executable stress is created by compiling `stress.cxx`. It completes
-sixteen tests covering the following capabilities of the ROOT framework.
-
--   Functions, Random Numbers, Histogram Fits
-
--   Size & compression factor of a ROOT file
-
--   Purge, Reuse of gaps in **`TFile`**
-
--   2D Histograms, Functions, 2D Fits
-
--   Graphics & PostScript
-
--   Subdirectories in a ROOT file
-
--   **`TNtuple`**, Selections, **`TCutG`**, **`TEventList`**
-
--   Split and Compression modes for Trees
-
--   Analyze `Event.root` file of stress 8
-
--   Create 10 files starting from `Event.root`
-
--   Test chains of Trees using the 10 files
-
--   Compare histograms of test 9 and 11
-
--   Merging files of a chain
-
--   Check correct rebuilt of `Event.root` in test 13
-
--   Divert Tree branches to separate files
-
--   Cling test (3 nested loops) with `LHCb` trigger
-
-The program stress takes one argument, the number of events to process.
-The default is 1000 events. Be aware that executing stress with 1000
-events*will create several files consuming about 100 MB of disk space;*
-running stress with 30 events will consume about 20 MB. The disk space
-is released once stress is done.
-
-There are two ways to run `stress`:
-
-From the system prompt or from the ROOT prompt using the interpreter.
-
-``` {.cpp}
-> cd $ROOTSYS/test
-> stress             // default 1000 events
-> stress 30          // test with 30 events
-```
-
-Start ROOT with the batch mode option (-b) to suppress the graphic
-output.
-
-``` {.cpp}
-> root -b
-root[] .L stress.cxx
-root[] stress(1000)// test with 1000 events
-root[] stress(30)// test with 30 events
-```
-
-The output of stress includes a pass/fail conclusion for each test, the
-total number of bytes read and written, and the elapsed real and CPU
-time. It also calculates a performance index for your machine relative
-to a reference machine a DELL Inspiron 7500 (Pentium III 600 MHz) with
-256 MB of memory and 18GB IDE disk in ROOTMARKS. Higher ROOTMARKS means
-better performance. The reference machine has 200 ROOTMARKS, so the
-sample run below with 53.7 ROOTMARKS is about four times slower than the
-reference machine.
-
-Here is a sample run:
-
-``` {.cpp}
-% root -b
-root[] .x stress.cxx(30)
-
-Test  1 : Functions, Random Numbers, Histogram Fits............. OK
-Test  2 : Check size & compression factor of a Root file........ OK
-Test  3 : Purge, Reuse of gaps in TFile......................... OK
-Test  4 : Test of 2-d histograms, functions, 2-d fits........... OK
-Test  5 : Test graphics & PostScript ............................OK
-Test  6 : Test subdirectories in a Root file.................... OK
-Test  7 : TNtuple, selections, TCutG, TEventList.......... OK
-Test  8 : Trees split and compression modes..................... OK
-Test  9 : Analyze Event.root file of stress 8................... OK
-Test 10 : Create 10 files starting from Event.root.............. OK
-Test 11 : Test chains of Trees using the 10 files............... OK
-Test 12 : Compare histograms of test 9 and 11................... OK
-Test 13 : Test merging files of a chain......................... OK
-Test 14 : Check correct rebuilt of Event.root in test 13........ OK
-Test 15 : Divert Tree branches to separate files................ OK
-Test 16 : Cling test (3 nested loops) with LHCb trigger.......... OK
-******************************************************************
-*  IRIX64 fnpat1 6.5 01221553 IP27
-******************************************************************
-stress    : Total I/O =   75.3 Mbytes, I =   59.2, O =  16.1
-stress    : Compr I/O =   75.7 Mbytes, I =   60.0, O =  15.7
-stress    : Real Time = 307.61 seconds Cpu Time = 292.82 seconds
-******************************************************************
-*  ROOTMARKS =  53.7   *  Root2.25/00   20000710/1022
-```
-
-### guitest - A Graphical User Interface
-\index{GUI application}
-
-The `guitest` example, created by compiling `guitest.cxx`, tests and
-illustrates the use of the native GUI widgets such as cascading menus,
-dialog boxes, sliders and tab panels. It is a very useful example to
-study when designing a GUI. Some examples of the output of `guitest` are
-shown next. To run it type `guitest` at the system prompt in the
-`$ROOTSYS/test` directory. We have included an entire chapter on this
-subject where we explore `guitest` in detail and use it to explain how
-to build our own ROOT application with a GUI. See "Writing a Graphical
-User Interface".
-
-![Native GUI widgets](pictures/030001FC.png)
diff --git a/documentation/users-guide/WebDisplay.md b/documentation/users-guide/WebDisplay.md
deleted file mode 100644
index dcf60bfe84004..0000000000000
--- a/documentation/users-guide/WebDisplay.md
+++ /dev/null
@@ -1,244 +0,0 @@
-# Web-based display
-
-In this chapter discussed how web-based display can be created in the ROOT.
-
-## Basics
-
-Idea of web displays is implementation of user interface, which can run remotely
-or locally in the web-browsers, fully decoupled from the application code.
-For the communication between application and browser websockets are used.
-On the server side ROOT application runs THttpServer instance which serves one or
-several clients. Client is any web browser
-
-
-## Creating web-window
-
-**`ROOT::RWebWindow`** class is represent window instance, which can be displayed in the browser
-
-```{.cpp}
-
-auto win = ROOT::RWebWindow::Create();
-
-// set HTML page which is showed when window displayed
-win->SetDefaultPage("file:page.html"); // set
-
-// allow unlimited user connections to the window (default only 1)
-ROOT::RWebWindowsManager::SetSingleConnMode(false);
-win->SetConnLimit(0);
-
-// configure predefined geometry
-win->SetGeometry(300, 300);
-
-```
-
-## Communication
-
-To receive data from the browser, data callback should be assigned.
-Callback is invoked when data received from the client or when connection is established.
-Normally lambda function is used:
-
-```{.cpp}
-
-win->SetDataCallBack([](unsigned connid, const std::string &msg) {
-
-   printf("Msg:%s from connection:%u\n", msg.c_str(), connid);
-
-});
-
-```
-
-Here **connid** is unique identifier, which assign to each connection when it is established.
-The connection identifier should be used when sending message to the client:
-
-```{.cpp}
-
-unsigned connid = win->GetConnectionId(); // first connection
-std::string msg = "Hello, world";
-win->Send(connid, msg);
-
-```
-
-## Client code
-
-The minimal HTML/JavaScript code, which establish connection with the server, looks like:
-
-```{html}
-<!DOCTYPE HTML>
-<html>
-   <head>
-      <meta charset="utf-8">
-      <title>RWebWindow Example
-      
-   
-   
-      
- - - - -``` - -Here `jsroot/webwindow` module is loaded to let establish connection with ROOT application. -It includes all necessary initialization and authentication of websocket connection with the server. -Beside this part there is no limitations which HTML/JS framework should be used to organize layout and code on the client side. - - -## Display window - -To configure web display one uses `--web=` argument when starting ROOT. -Typical values are: - -- "chrome": select Google Chrome browser for interactive web display -- "firefox": select Mozilla Firefox browser for interactive web display -- "edge": select Microsoft Edge browser for interactive web display -- "qt6": uses QWebEngine from Qt6, no real http server started (requires `qt6web` component build for ROOT) -- "cef": uses Chromium Embeded Framework, no real http server started (requires `cefweb` component build for ROOT) -- "default": system default web browser, invoked with `xdg-open` on Linux, `start` on Mac or `open` on Windows -- "off": turns off the web display and comes back to normal graphics in interactive mode. - -Alternatively one can call `gROOT->SetWebDisplay("")` to specify display kind. -Same argument can be provided directly to the `RWebWindow::ShowWindow()`. - -With the method `win->GetUrl()` one obtains URL string, which can be typed in the browser address string directly. - - -## Use window in multi-threads application - -It it highly recommended to always use same `RWebWindow` instance from the same thread. -Means if one plans to use many threads running many web window, -one should create, communicate and destroy window from that thread. -In such situation one avoids need of extra locks for handling window functionality. - -When `RWebWindow` object is created, it store thread `id`. That `id` always checked when communication with the client is performed. -One can change this thread `id` by `RWebWindow::AssignThreadId()` method, but it should be done in the beginning before communication -with client is started. Communication callbacks from the RWebWindow invoked always in context of thread `id`. - -To let handle window communication with the client, one should regularly call `RWebWindow::Run()` method. -It runs send/receive operations and invoke user call-backs. As argument, one provides time in seconds. -Alternatively, one can invoke `RWebWindow::Sync()` which only handle queued operations and does not block thread for the long time. - -There are correspondent `RWebWindow::WaitFor()` and `RWebWindow::WaitForTimed()` methods which allow not simply run window functionality -for the long time, but wait until function returns non-zero value. - - -## Run web-canvas in multiple threads - -`TWebCanvas` in web implementation for `TCanvas` class. It is allowed to create, modify and update canvases -from different threads. But as with `RWebWindow` class, it is highly recommended to work with canvas always from the same thread. -Also objects which are drawn and modified in the canvas, should be modified from this thread. - -`TWebCanvas` is automatically created for `TCanvas` when root started with `--web` argument or `gROOT->SetWebDisplay()` in invoked. -One also can use `TWebCanvas::CreateWebCanvas()` method which creates canvas with pre-configured web implementation. - -Of the main importance is correct usage of `TCanvas::Update()` method. If canvas runs in special thread, -one should regularly invokde `canv->Upated()` method. This not only updates drawing of the canvas on the client side, -but also perform all necessary communication and callbacks caused by client interaction. - -If there are many canvases run from the same thread, one probably can enable async mode of the `TWebCanvas` by -calling `TWebCanvas::SetAsyncMode(kTRUE)`. This let invoke updates of many canvases without blocking caller thread - -drawing will be performed asynchronousely in in the browser. - - -## Use of i/o threads of `civetweb` servers - -`THttpServer` class of ROOT uses `civetweb` for implementing communication over http protocol. -It creates and run several threads to reply on http requests and to run websockets. -Normally recevived packets queued and processed afterwards in the thread where `RWebWindow` created and run. -All this involves mutexes locking and condition wait - which costs extra time. - -DANGEROUS! To achive maximal responsiveness and minimal latency one can enable direct usage of `civetweb` threads by -calling `RWebWindow::UseServerThreads()`. In this case callbacks directly in context of `civetweb` threads at the moment when -data received from websocket. One can immediately send new message to websocket - and this will be the fastest way to communicate -with the client. But one should care about proper locking of any data which can be accessed from other application threads. - -Example of such threads usage is `tutorials/visualisation/webgui/ping` example. - - -## Embed widgets for connection sharing - -Each websocket connection consume resources of `civetweb` server - which uses one thread per connection. -If many connection are required, one can increase number of threads by specifying `WebGui.HttpThrds` parameter in rootrc file. - -But it is possible to share same connection between several widgets. -One such example can be found in `tutorials/visualisation/webgui/bootstrap` demo, where canvas embed into larger bootstrap widget. -In general case following steps are performed: - -- create channel on the client side and send id to the server -```javascript - const new_conn = handle.createChannel(); - new_conn.setReceiver({ onWebsocketMsg(h, msg) { console.log(msg) } }); - handle.send('channel:' + new_conn.getChannelId()); -``` -- on the server one extracts channel id and embed new RWebWindow instance to main: -```cpp - if (msg.compare(0, 8, "channel:") == 0) { - int chid = std::stoi(msg.substr(8)); - printf("Get channel request %d\n", chid); - auto new_window = RWebWindow::Create(); - new_window->SetDataCallBack(...); - RWebWindow::ShowWebWindow(new_window, { main_window, connid, chid }); - } -``` - -From this point `new_window` instance will be able to use `new_conn` created on the client side. -This is exactly the way how `TWebCanvas` embed in bootstrap example or -many different widget kinds embed in `RBrowser`. -At some point probably one may need to increase default credits numbers for the connection by setting -`gEnv->SetValue("WebGui.ConnCredits", 100);` before starting main widget. - - -## Use ROOT web widgets on the remote nodes - -It is advised to use the `rootssh` script with built-in port forwarding and run -the user interface on the local host with the default web browser. Like: - - [localhost] rootssh username@remotenode - -As with regular `ssh`, one can specify command which should be run on remote node: - - [localhost] rootssh username@remotenode "root --web -e 'new TBrowser'" - -Script automatically creates tunnel and configures several shell variables in remote session. These are: - -- `ROOT_WEBGUI_SOCKET` - unix socket which will be used by ROOT `THttpServer` in webgui -- `ROOT_LISTENER_SOCKET` - unix socket which gets messages from ROOT when new web widgets are started - -When on remote node in ROOT session new web widget is created, default web browser will be started on the local node and display created widget. - -It is highly recommended to use `rootssh` script on public nodes like `lxplus`. Unix sockets, which are created on -the remote session, are configured with `0700` file mode - means only user allowed to access them. - -One can provide `--port number` parameter to configure port number on local node and `--browser ` to specify -web browser executable to display web widgets. Like: - - [localhost] rootssh --port 8877 --browser chromium username@remotenode - -Also any kind of normal `ssh` arguments can be specified: - - [localhost] rootssh -Y -E file.log username@remotenode - -On remote node root session should be started with `root --web` argument to advise ROOT use web widgets. Like: - - [remotehost] root --web hsimple.C - -[`rootssh` script](https://raw.githubusercontent.com/root-project/root/master/config/rootssh) can be download and used independently from ROOT installation - it is only required that supported ROOT version installed on remote node. - - diff --git a/documentation/users-guide/WritingGUI.md b/documentation/users-guide/WritingGUI.md deleted file mode 100644 index cdc9c3b9c14ea..0000000000000 --- a/documentation/users-guide/WritingGUI.md +++ /dev/null @@ -1,2884 +0,0 @@ -# Writing a Graphical User Interface -\index{Graphical User Interface} - -The ROOT GUI classes support an extensive and rich set of widgets with -the Windows 95 look and feel. The widget classes interface to the -underlying graphics system via a single abstract class. Concrete -versions of this abstract class have been implemented for X11 and Win32, -thereby making the ROOT GUI fully cross-platform. Originally the GUI -classes were based on Hector Peraza's Xclass'95 widget library - - -## The ROOT GUI Classes - - -Features of the GUI classes in a nutshell: - -- Originally based on the Xclass'95 widget library - -- A rich and complete set of widgets - -- Win'95 look and feel - -- All machine dependent graphics calls abstracted via the - **`TVirtualX`** "abstract" class - -- Completely scriptable via the C++ interpreter (fast prototyping) - -- Supports signal/slot event handling as pioneered by Trolltech's Qt - -- Full class documentation is generated automatically (as for all ROOT - classes) - -- Code generation for variety of GUI's - -## Widgets and Frames - - -The ROOT GUI classes provide of set of components that allow an easy way -to develop cross-platform GUI applications with a Windows look and feel. - -The main widgets are: - -- Simple widgets: labels, icons, push buttons, either with text or - pixmaps, check buttons, radio buttons, menu bars and popup menus, - scroll bars, list boxes, combo boxes, group frames, text entry - widgets, tab widgets, progress bars, sliders, tool tips - -- Complex widgets: shutter, toolbar, status bar, list view, list tree - -- Common dialogs: File Open/Save, File Properties, Font Selection, - Color Selection, About - -- The widgets are shown in frames: - -- frame, composite frame, main frame, transient frame, group frame - -- Arranged by layout managers: - -- horizontal layout, vertical layout, row layout, list layout, tile - layout, matrix layout - -Using a combination of layout hints: - -- left, right, center x, center y, top, bottom, expand x, expand y, - fixed offsets - -Event handling by signals/slots and messaging (as opposed to callbacks): - -- in response to actions widgets send messages and emit signals - -- associated frames process these messages or the slot methods - connected to the signals are executed - -## TVirtualX - - -The GUI classes interface to the platform dependent low level graphics -system via the semi-abstract graphics base class **`TVirtualX`**. -Currently concrete implementations exist for X11 and Win32 (MacOS X is -fully supported via Apple's X11 implementation). Thanks to this single -graphics interface, porting the ROOT GUI to a new platform requires only -the implementation of **`TVirtualX`**. - -![](pictures/02000201.jpg) - -## A Simple Example - - -We will start with a simple example that builds a small application -containing a canvas and two buttons: Draw and Exit. Its functionality -will be very simple: every time you click on Draw button, the graphics -of the function `sin(x)/x` will be drawn in randomly chosen interval in -the canvas window, if you click on Exit - you close the application. -This example shows the basic concepts for almost any GUI-application in -ROOT and it is important to understand how it is constructed. The -example program is written as a named script. See "Cling the C++ -Interpreter". Remember that the named script can be executed via - -``` {.cpp} -root[] .x example.C -``` - -only if the filename (without extension) and the function entry point -are both the same. - -![](pictures/02000202.jpg) - -We need to say a few words about the parent-children relationship -between the widgets before going through the real code. The widgets' -behaviors are based on this relationship. Every parent widget is -responsible for where the children are and it ensures all properties and -behavior for them. For example, if you want to hide several widgets, it -will be enough to hide their parent widget. Later you can show the -parent and the children will appear too. Writing your code you have to -specify the parent-child relationship. Usually in a child constructor -the address of the parent is passed as an argument. In general frames -are parents of simple widgets. In this example you will see how we -organize the parent-children relationship by using frame widgets in -addition to the canvas window and button widgets. - -Let's now go through the code of the `example.C`. - -The first lines include ROOT header files. The header file names are -almost always as the class names (**`TApplication`**, **`TF1`**, -**`TCanvas`**), but there are cases when similar classes are grouped -together in one header file: all frames are declared in `TGFrame.h`, all -buttons - in `TGButton.h`, etc. Our small example is based on an object -of the class `MyMainFrame`. - -``` {.cpp} -new MyMainFrame(gClient->GetRoot(),200,200); -``` - -The first parameter `gClient->GetRoot()` makes the initial connection to -the window server. It is a pointer to the root window of the screen, -which is obtained from ***`gClient`***. The next two parameters -initialize the width and height of the application window in pixels. Let -see what `MyMainFrame` is. The three arguments pass to the -**`TGMainFrame`** constructor when we create the `fMain` object. - -The first thing to note is the inclusion of the `RQ_OBJECT` macro in the -class declaration of `MyMainFrame`. It is necessary to provide a -standalone class signal/slot capability. The signal/slot communication -mechanism is described in a separate chapter. See "Event Processing: -Signals and Slots". - -``` {.cpp} -// example.C - -#include -#include -#include -#include -#include -#include -#include -#include - -class MyMainFrame { - RQ_OBJECT("MyMainFrame") -private: - TGMainFrame *fMain; - TRootEmbeddedCanvas *fEcanvas; -public: - MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h); - virtual ~MyMainFrame(); - void DoDraw(); -}; -MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) { - // Create a main frame - fMain = new TGMainFrame(p,w,h); - - // Create canvas widget - fEcanvas = new TRootEmbeddedCanvas("Ecanvas",fMain,200,200); - fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY, 10,10,10,1)); - // Create a horizontal frame widget with buttons - TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain,200,40); - TGTextButton *draw = new TGTextButton(hframe,"&Draw"); - draw->Connect("Clicked()","MyMainFrame",this,"DoDraw()"); - hframe->AddFrame(draw, new TGLayoutHints(kLHintsCenterX, - 5,5,3,4)); - TGTextButton *exit = new TGTextButton(hframe,"&Exit", - "gApplication->Terminate(0)"); - hframe->AddFrame(exit, new TGLayoutHints(kLHintsCenterX, - 5,5,3,4)); - fMain->AddFrame(hframe, new TGLayoutHints(kLHintsCenterX, - 2,2,2,2)); - - // Set a name to the main frame - fMain->SetWindowName("Simple Example"); - - // Map all subwindows of main frame - fMain->MapSubwindows(); - - // Initialize the layout algorithm - fMain->Resize(fMain->GetDefaultSize()); - - // Map main frame - fMain->MapWindow(); -} -void MyMainFrame::DoDraw() { - // Draws function graphics in randomly chosen interval - TF1 *f1 = new TF1("f1","sin(x)/x",0,gRandom->Rndm()*10); - f1->SetLineWidth(3); - f1->Draw(); - TCanvas *fCanvas = fEcanvas->GetCanvas(); - fCanvas->cd(); - fCanvas->Update(); -} -MyMainFrame::~MyMainFrame() { - // Clean up used widgets: frames, buttons, layout hints - fMain->Cleanup(); - delete fMain; -} -void example() { - // Popup the GUI... - new MyMainFrame(gClient->GetRoot(),200,200); -} -``` - -The **`TGMainFrame `**class defines a top level window that interacts -with the system window manager. Its method `CloseWindow()` is invoked -when Alt+F4 are pressed or a window manager close/exit command is used. -To terminate the application when this happens you need to override the -`CloseWindow()` method and call `gApplication->Terminate(0)`. - -The main frame can be considered as a container where all widgets of the -application are organized with respect to their parent-child -relationship. After the main frame we create `fEcanvas` - an object of -class **`TRootEmbeddedCanvas`**. It is a quite complex widget and we -will explain it in detail later. For the moment keep in mind only its -main purpose - to create a **`TCanvas`** - the ROOT basic whiteboard for -drawing and editing different graphical objects. - -``` {.cpp} -fEcanvas = new TRootEmbeddedCanvas("Ecanvas",fMain,200,200); -``` - -In the **`TRootEmbeddedCanvas`** constructor we pass the address of the -main frame widget `fMain` as a second parameter. This pass is important -because it makes `fMain` the parent of the canvas window. The first -parameter `Ecanvas` is the name of the **`TCanvas`**, the last two -parameters give the width and height of canvas window in pixels. Next -step is to add `fEcanvas` to the parent frame defining its appearance -inside the parent window. We use the method `AddFrame():` - -``` {.cpp} -fMain->AddFrame(fEcanvas,new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY, 10, 10, 10, 1)); -``` - -It adds the `fEcanvas` into the list of children widgets of the main -frame `fMain`. The specification of how it should be placed inside the -parent frame is made by the **`TGLayoutHints`** object. Setting its -first parameter to `kLHintsExpandX|kLHintsExpandY `we define the canvas -window as expanded on x and y in the frame. The next four parameters -define amounts of padding in left, right, top and bottom in pixels. This -means that the canvas window will be expanded when the parent window -expands, but it will keep around a frame of 10 pixels on left, right, -top and 1 pixel on bottom. - -![](pictures/02000203.jpg) - -The laying out is always made with respect to the parent-children -relationship. There is a special chapter presenting the different layout -managers, but we will quickly introduce the concept here. The layout -process will apply not to the embedded canvas window but to its parent - -the main frame. A popular layout manager and the one used in this case -is the vertical layout manager which arranges its widgets vertically in -a column. - -The next widget we create as a child of the main frame is the horizontal -frame `hframe`: - -``` {.cpp} -TGHorizontalFrame *hframe=new TGHorizontalFrame(fMain,200,40); -``` - -The first parameter of its constructor is again the address of its -parent, `fMain`. The next ones define the frame width and height in -pixels. The name of the class **`TGHorizontalFrame`** gives a hint that -a horizontal layout will apply on its children widgets. The Draw and -Exit buttons will be laid out horizontally. Here are their constructors: - -``` {.cpp} -TGTextButton *draw = new TGTextButton(hframe,"&Draw"); -hframe ->AddFrame(draw, new TGLayoutHints(kLHintsCenterX,5,5,3,4)); -TGTextButton *exit = new TGTextButton(hframe,"&Exit", - "gApplication->Terminate(0)"); -hframe ->AddFrame(exit,new TGLayoutHints(kLHintsCenterX,5,5,3,4)); -``` - -They are created as objects of the **`TGTextButton`** class that -represent the command buttons with a text label. When you click on a -command button it performs the action shown on its label. These buttons -are well known as "push buttons" or just "buttons". The parent address -`hframe` is passed as first parameter. The second one defines the button -label and normally indicates the action to be taken when the button is -clicked. It is possible to define a hot key for the button at that point -using the hot string for its label. A hot string is a string with a -"hot" character underlined. This character we call the button hot key. -It shows the assigned keyboard mnemonic for the button choice. Following -our example, this means that you can use `Alt+D` to click on Draw button -and `Alt+E` to click on Exit. There is a possibility to specify a -command string as third parameter of the button constructor. We use it -to assign the command `gApplication->Terminate(0)`. The application will -be terminated when you click on the Exit button. - -We call again `AddFrame()` to add the buttons to their parent widget -giving layout hints for each of them. This time we would like to have -centered buttons with an amount of 5 pixels on the left, 5 on the right, -3 on the top and 4 on the bottom. You can feel already that the same -steps are repeated three times: to create a new widget with passing a -parent address as a parameter, to define layout hints for it and to add -it in the parent list. The next line is something new: - -``` {.cpp} -draw->Connect("Clicked()","MyMainFrame",this,"DoDraw()"); -``` - -Here we connect a signal to a slot. Whenever the draw button is clicked, -it emits a signal that something has happened (it is clicked) to whom -might be interesting in the outside world. The widget does not know who -will use this information. On the other side of the program world there -is some code which should be executed when the button is clicked. This -code is called a slot. Think about slots as normal C++ functions or -class methods. The line above specifies that the slot -`MyMainFrame::DoDraw()` will be executed when the draw button is -clicked. Our slot draws the graphics of `sin(x)/x` in randomly chosen -interval every time the draw button sends a signal "I am clicked". The -signal/slot communication mechanism originally featured in Qt by -TrollTech(see ). ROOT -supports its own version of signals/slots. We will return to that point -in details later. We specified all child widgets of the horizontal frame -(the Draw and Exit buttons in our case). Next, we need to add their -parent frame to the main frame: - -``` {.cpp} -fMain->AddFrame(hframe,new TGLayoutHints(kLHintsCenterX,2,2,2,2)); -``` - -The last thing to do is to set the main window title and to make all -widgets visible. Commonly in all systems windows are assigned by name to -be identified by users. This name is displayed in the application's -title bar and can be set by: - -``` {.cpp} -fMain->SetWindowName("Simple Example"); -``` - -The next lines make the widgets visible. The first one maps all child -frames of the top-level frame; the last one - the main frame itself, -i.e. makes it appear on the screen. - -``` {.cpp} -fMain->MapSubwindows(); -fMain->Resize(fMain->GetDefaultSize()); -fMain->MapWindow(); -``` - -The line in between has an important mission - to execute all layout -specifications for the widgets before the top-level window itself is -shown on the screen. We can run the named script via the Cling -interpreter with the command: - -``` {.cpp} -root[].x example.C -``` - -The event processing starts. If you change the state of a widget, it -emits a signal and the corresponding slot is executed ensuring the -functionality we want for this small example. - -The steps we passed can be generalized as follows: - -- Opening of the connection to the system - -- Definition of main frame (top level window) - -- Creation of widgets as children of the top-level frame; assign them - desired properties following the steps: - -- Create a new widget passing its parent in the constructor - -- Connect widget's signals with desired slots to ensure desired - functionality - -- Define widget's layout and add it to the parent list of children - -- Set main window attributes - -- Map all sub windows - -- Initialize the layout algorithm via `Resize(GetDefaultSize())` - method - -- Map the main frame - -- Execution of the even-processing loop - -### A Standalone Version - - -As usual a standalone program in C++ has to contain a main() function - -the starting point for the application execution. In this case it is -better to separate the program code creating a program header file -example2a.h with the `MyMainFrame` class declaration and -`example2a.cxx `- with the class methods implementation. To run our -simple example as a standalone application we need to create in addition -an object of class **`TApplication`**. It will make a correct -initialization of the dictionaries if it is not yet done. It will be -responsible for holding everything together and to handle all events in -the application. Its environment provides an interface to the ROOT -graphics system and by calling the `Run()` method the event loop starts -and the application program is waiting for the user action. The -application exits only if the top level window is not closed. Two header -files are used in addition: `TApplication.h` - for the class -**`TApplication`** and `TGClient.h` that is used to make initial -connection to the graphics system. The class **`TApplication`** must be -instantiated only once in any given application. The original list of -argument options can be retrieved via the `Argc()` and `Argv()` methods. - -Note: to have signals/slots working we need to create a dictionary for -the class `MyMainFrame`, i.e. we create the file `ex2aLinkDef.h` -containing the line: - -``` {.cpp} -#pragma link C++ class MyMainFrame; -``` - -We compile the example: - -``` {.cpp} -rootcling -f ex2aDict.cxx -c example2a.h ex2aLinkDef.h -g++ -o example2a example2a.cxx ex2aDict.cxx `root-config --cflags --glibs` -``` - -`example2a.h` - -``` {.cpp} -#include -#include - -class TGWindow; -class TGMainFrame; -class TRootEmbeddedCanvas; - -class MyMainFrame { - RQ_OBJECT("MyMainFrame") -private: - TGMainFrame *fMain; - TRootEmbeddedCanvas *fEcanvas; -public: - MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h); - virtual ~MyMainFrame(); - void DoDraw(); -}; -``` - -`example2a.cxx` - -``` {.cpp} -#include -#include -#include -#include -#include -#include -#include -#include "example2a.h" - -MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) {...} -MyMainFrame::~MyMainFrame() { ... } -void MyMainFrame::DoDraw() { ... } -void example() { ... } - -int main(int argc, char **argv) { - TApplication theApp("App",&argc,argv); - example(); - theApp.Run(); - return 0; -} -``` - -The class `MyMainFrame` could derive from **`TGMainFrame`**. In that -case the `RQ_OBJECT` macro is not needed anymore, since the -functionality it provides is obtained now via inheritance from -**`TGMainFrame`**. This will reflect in the `MyMainFrame` class -declaration and in the code of the `MyMainFrame::MyMainFrame` -constructor as follows: - -`example2b.h` - -``` {.cpp} -#include -class MyMainFrame : public TGMainFrame { -private: - TRootEmbeddedCanvas *fEcanvas; -public: - MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h); - virtual ~MyMainFrame() { ... } - void DoDraw(){ ... } - ClassDef(MyMainFrame,0) -}; -``` - -`example2b.cxx` - -``` {.cpp} -#include -#include -#include -#include -#include -#include -#include -#include "example2b.h" - -MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) - : TGMainFrame(p,w,h) { - - // Creates widgets of the example - fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",this,200,200); - AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY, 10,10,10,1)); - TGHorizontalFrame *hframe=new TGHorizontalFrame(this, 200,40); - TGTextButton *draw = new TGTextButton(hframe,"&Draw"); - draw->Connect("Clicked()","MyMainFrame",this,"DoDraw()"); - hframe->AddFrame(draw, new TGLayoutHints(kLHintsCenterX, - 5,5,3,4)); - TGTextButton *exit = new TGTextButton(hframe,"&Exit ", - "gApplication->Terminate()"); - hframe->AddFrame(exit, new TGLayoutHints(kLHintsCenterX, - 5,5,3,4)); - AddFrame(hframe,new TGLayoutHints(kLHintsCenterX,2,2,2,2)); - - // Sets window name and shows the main frame - SetWindowName("Simple Example"); - MapSubwindows(); - Resize(GetDefaultSize()); - MapWindow(); -} -``` - -## Widgets Overview - - -The word widget is a contraction of windows and gadget. Almost all GUI -elements are widgets. A button is a widget, a menu item is a widget, a -scrollbar is a widget, and a complete dialog box is a widget too. Some -widgets may have sub widgets. For example, a dialog box can contain -buttons, text fields, a combo-box, etc. - -On the screen widgets look like rectangular areas with special -behaviors. In terms of the object-oriented programming we can define a -widget in ROOT as an object of a class deriving from **`TGObject`**. - -This section presents all currently supported widgets in ROOT and their -most useful methods. All of them can be considered as building blocks -for an application, and most of them can be found in dialogs. Provided -snippets of the code will give you practical guidelines where and how to -use certain widgets. The macro `$ROOTSYS/tutorials/visualisation/gui/guitest.C` -contains the complete source code. - -![Widgets created by ROOT GUI classes](pictures/02000204.jpg) - -Any custom widget can be created by sub classing existing widgets. To -achieve a better understanding of the widgets' properties they are -separated by their type and their inheritance. As all of them inherit -from **`TGObject`** and most from **`TGWidget`**, these base classes are -described first. - -### TGObject - - -**`TGObject`** is the base class for all ROOT GUI classes. It inherits -from **`TObject`**. The two data members of this class contain important -information about X11/Win32 window identifier and the connection to the -host's graphics system. Every GUI element, which derives from -**`TGObject`** has access to the **`TGClient`** via the data member -`fClient` of **`TGObject. TGClient`** creates the connection with the -host's graphics system and sets up the complete graphics system for all -widgets. - -### TGWidget - - -The widgets base class **`TGWidget`** is typically used as a mix-in -class via multiple inheritances. Its properties are available for all -deriving widgets: **`TGButton`**, **`TGComboBox`**, **`TGTab`**, -**`TGColorPalette`**, **`TGColorPick`**, **`TGDoubleSlider`**, -**`TGListTree`**, **`TGNumberEntry`**, **`TGScrollBar`**, -**`TGShutterItem`**, **`TGTextEntry`**, **`TGSlider`**, **`TGListBox`**, -**`TGView.`** - -This class has four data members keeping information about the widget id -- important for event processing, the window which handles the widget's -events, the widget status flags and the assigned command (if there is -any). The general properties of **`TGWidget`** are specified by -`SetFlags(Int_t flags)` and `ClearFlags(Int_t flags)` methods. The -status flags are: `kWidgetWantFocus`, `kWidgetHasFocus`, and -`kWidgetIsEnabled`. The method `Associate(const TGWindow* w)` - sets the -window which handles the widget events. -`SetCommand(const char* command)` - sets the command to be executed. The -command string can be gathering via `GetCommand()` method. For example, -the third parameter in **`TGTextButton`** constructor can be omitted and -set later in your program, i.e. instead of: - -``` {.cpp} -TGTextButton *exit = new TGTextButton(hframe,"&Exit", - "gApplication->Terminate()"); -``` - -You will have the following the two lines: - -``` {.cpp} -TGTextButton *exit = new TGTextButton(hframe,"&Exit"); -exit->SetCommand("gApplication->Terminate()"); -``` - -The method `IsEnabled()` - returns `kTRUE` if the widget has flag -`kWidgetIsEnabled` and it accepts user events. This method is very -important for creating a good user interface because it allows you to -disable or enable a widget depending on the situation of your -application. As a standard all disabled widgets are displayed "grayed -out". `HasFocus()` - returns `kTRUE` if the widget has the input focus -(i.e. flag `kWidgetHasFocus` is set). Remember that only one item in a -complex widget as a dialog can have the value of `HasFocus()` sets as -true. `WantFocus()` - returns `kTRUE` if the flag `kWidgetWantFocus` is -set. - -### TGWindow - - -**`TGWindow`** is a ROOT GUI window base class. It inherits from -**`TGObject`** and **`TGFrame`** derives from it. The application does -not use it directly. It creates and registers a new window within the -system. This window has common characteristics: existing parent, -location, size in height and width (it has a default minimum size 1, 1 -under which it cannot shrink), border with particular view, state, -specific attributes. If there are no specified arguments their values -will be taken from the parent. It receives events from the window system -and can paint a representation of itself on the screen. - -![](pictures/02000205.jpg) - -### Frames - - -Most of the frame classes are mainly created for arranging widgets in a -window. The class **`TGFrame`** is a subclass of **`TGWindow`** -providing additional window characteristics and overriding some methods -of **`TGWindow`**. It is a base class for the simple widgets as buttons, -labels, etc. Its only purpose is to draw a frame around widgets that do -not have a frame of their own. The main groups of **`TGFrame`** member -functions are: - -- Window's functions: `DoRedraw()`, `DeleteWindow()`, `Activate()`, - etc. - -- Geometry functions: `Move()`, `Resize()`, `SetSize()`, etc. - -- Graphics handlers: `ChangeBackground()`, `ChangeOptions()`, etc. - -- Mouse and keyboard functions: `HandleButton()`, - `HandleFocusChange()`, `HandleKey()`, `HandleMotion()`, etc. - -- Event handlers: `HandleEvent()`, `ProcessEvent()`, `GetSender()`, - `SendMessage()`,` ProcessMessage()`, `GetLastClick()`, etc. - -![The GUI classes hierarchy](pictures/02000206.jpg) - -Ones of **`TGFrame`** member functions provide direct functionality; -others - will be overridden by **`TGFrame`** subclasses to ensure -particular widget's functionality. There are two constructors provided -in **`TGFrame`** class. One creates a frame using an externally created -window: - -``` {.cpp} -TGFrame(TGClient *c,Window_t id,const TGWindow *parent = 0); -``` - -For example, it can register the root window (called by **`TGClient`**), -or a window created via **`TVirtualX::InitWindow()`** (window id is -obtained by `TVirtualX::GetWindowID()` method). The other -**`TGFrame`** constructor is: - -``` {.cpp} -TGFrame(const TGWindow *p,UInt_t w,UInt_t h,UInt_t options=0, -ULong_t back = GetDefaultBackground()); -``` - -The options parameter is the bitwise OR between defined frame types. -Here is a short description of these types: - -+-----------------------+----------------------------------------------------+ -| Frame Type | Description | -+-----------------------+----------------------------------------------------+ -| `kChildFrame ` | a frame embedded in a parent | -+-----------------------+----------------------------------------------------+ -| `kMainFrame ` | a main frame interacting with the system Window | -| | Manager | -+-----------------------+----------------------------------------------------+ -| `kTransientFrame ` | a top level dialog's frame | -+-----------------------+----------------------------------------------------+ -| `kVerticalFrame ` | a frame that layouts its children in a column | -+-----------------------+----------------------------------------------------+ -| `kHorizontalFrame ` | a frame that layouts its children in a row | -+-----------------------+----------------------------------------------------+ -| `kSunkenFrame ` | a frame with a sunken board appearance | -+-----------------------+----------------------------------------------------+ -| `kRaisedFrame ` | a frame with a raised board appearance | -+-----------------------+----------------------------------------------------+ -| `kFitWidth ` | a frame with dynamically scaled width | -+-----------------------+----------------------------------------------------+ -| `kFitHeight ` | a frame with dynamically scaled height | -+-----------------------+----------------------------------------------------+ -| `kFixedWidth ` | a frame with fixed width | -+-----------------------+----------------------------------------------------+ -| `kFixedHeight ` | a frame with fixed height | -+-----------------------+----------------------------------------------------+ -| `kFixedSize ` | = `kFixedWidth` | `kFixedHeight` | -| | | -| | a frame with fixed width and height | -+-----------------------+----------------------------------------------------+ -| `kDoubleBorder ` | a frame having a double line border | -+-----------------------+----------------------------------------------------+ -| `kOwnBackground ` | a frame having own background | -+-----------------------+----------------------------------------------------+ -| `kTempFrame ` | a temporary frame shown in certain circumstances; | -| | for example, it is used for creation of tool tip | -| | widget | -+-----------------------+----------------------------------------------------+ - -The method `ChangeOpton(UInt_t options)` allows you to change frame -options. Next example shows you how to change `kVerticalFrame` option to -`kHorizontalFrame`: - -``` {.cpp} -frame->ChangeOptions((frame->GetOptions()& ~kVerticalFrame) | - kHorizontalFrame); -``` - -The class **`TGCompositeFrame`** is the base class of all composite -widgets as a menu bar, a list box, a combo box, etc. It subclasses -**`TGFrame`** and has in addition a layout manager and a list of child -frames/widgets. There are two steps to do the design using a composite -frame widget. First you put all widgets you need within this frame and -assign them desired properties using `AddFrame(),` then you lay them out -by the `Layout()` method according to the assigned layout manager. The -method `AddFrame()` creates an instance of **`TGFrameElement`** class -for every child widget of a composite frame. This class has three public -data members: the child pointer, its layout hints, and a status variable -showing if the child is visible or hidden. If no hints are specified, -the default layout hints are used. Because the layout is very important -part of any design we include a special section about layout management -and layout hints. - -You can set a layout manager for the composite frame via: - -``` {.cpp} -compFrame->SetLayoutManager(TGLayoutManager *l); -``` - -The child widgets cannot be added to different composite frames. - -Any child frame can be removed from the parent list by: - -``` {.cpp} -compFrame->RemoveFrame(TGFrame *f); -``` - -You can hide or show a child frame of a composite frame using the -methods: `HideFrame(TGFrame *f)` or `ShowFrame(TGFrame *f).` You should -call, for example `HideFrame(TGFrame *f),` only after the frames have -been laid out and the sub windows of the composite frame have been -mapped via method `MapSubwindows(),` i.e. - -``` {.cpp} -frame->AddFrame(hFrame1,fLayout1); -frame->AddFrame(hFrame2,fLayout2); -frame->Resize(frame->GetDefaultSize()); // lays out frames -frame->MapSubwindows(); // maps subwindows -frame->HideFrame(hFrame2); // hides frame hFrame2 -frame->MapWindow(); // maps main frame -``` - -The state information about a child frame can be obtained from the -methods `GetState(TGframe *f)`, `IsArranged(TGFrame *f)`, and -`IsVisible(TGFrame *f)`. - -The method `Cleanup()` deletes all objects of the composite frame added -via `AddFrame()`. All **`TGFrameElement`** objects (frames and layout -hints) must be unique, i.e. cannot be shared. - -We already mentioned that **`TGMainFrame`** class defines top level -windows interacting with the system window manager. It handles -applications with a menu bar, toolbar, text entry fields and other -widgets surrounding a central area (e.g. a canvas widget). It lays out a -set of related widgets and provides the typical application main window -behavior. As you can see from the Figure above, it inherits from -**`TGCompositeFrame`** and is inherited by **`TGTransientFrame`** and -several ROOT interface classes: **`TViewerX3D`**,**` TRootBrowser`**, -**`TRootCanvas`**, **`TRootControlBar`**, **`TTreeViewer.`** - -To fix the size of a top level window you have to use the method -`TGMainFrame::SetWMSize().` This call tells the Window Manager that it -should not resize the window. The option `kFixedSize` works only for -embedded frames like **`TGCompositeFrame`** and derived classes (in -combination with layout hints). - -The **`TGVerticalFrame`** and **`TGHorizontalFrame`** are composite -frames that lay out their child frames in vertical or horizontal way in -the same order as they were added and according to their hints -preferences. - -The **`TGTransientFrame`** class defines transient windows that -typically are used for dialogs. They extend and complete an interaction -within a limited context. Always transient frames are displayed from -another window or another dialog. They may appear because of a command -button being activated or a menu item being selected. They may also -present automatically when an additional input and the user attention -are required by a certain condition. - -The **`TGGroupFrame`** class presents a very convenient frame which -surrounds visually a group of logically connected widgets: radio -buttons, related check boxes, two or more functionally related controls. - -![](pictures/02000207.jpg) - -It is a composite frame with a border and a title. The title explains -the purpose of the group and should be a noun or noun phrase. Here is an -example taken from `guitest.C`: - -``` {.cpp} -groupFrame = new TGGroupFrame(tf,"Options",kVerticalFrame); -groupFrame->SetTitlePos(TGGroupFrame::kLeft); -``` - -The second line sets the title position on the left. You can change it -to be centered or right aligned if you use **`TGGroupFrame::kCenter`** or -`TGGroupFrame::kRight` as a parameter. - -![](pictures/02000208.jpg) - -Be conservative in the use of borders because of the potential for -clutter. Do not place them around single entry fields, single combo -boxes, list boxes and groups of command buttons. The design of these -widgets provides them with a border. The picture above provides kind of -borders to avoid. - -## Layout Management - - -The layout process is an integral part of any GUI. When you create a -simple message window, laying out its few buttons and text widgets is -quite simple. However, this process becomes increasingly difficult if -you have to implement large GUI's with many widgets that should behave -properly when the GUI is resized or uses a different font type or size. -Layout management is the process of determining the size and position of -every widget in a container. - -A layout manager is an object that performs layout management for the -widgets within a container. You already know that when adding a -component (child widget) to a container (parent widget) you can provide -alignment hints (or rely on the default ones). These hints are used by -the layout manager to correctly position the widgets in the container. -The **`TGLayoutManager`** is an abstract class providing the basic -layout functionality. - -![The layout classes hierarchy](pictures/02000209.jpg) - -The base "container" class is **`TGCmpositeFrame`**. You can easily -change the layout manager using the -`SetLayoutManager(TGLayoutManager *l)` method. Setting the proper layout -manager for each container is the first step you have to do. The -container uses that layout manager to position and size the components -before they are painted. ROOT currently provides the layout managers -shown on the picture above. - -The next important step is to provide hints about every widget in the -container, i.e. to provide positions and right amount of space between -the components. The **`TGLayoutHints`** objects set hints by specifying -the white space in pixels around every widget. - -Let's see an example with five buttons. First you put them in a -container, assign them desired properties, and then you lay them out -according to the layout manager. This process can be repeated: you go -back and add, remove or change some of the widgets and lay them out -again. - -![](pictures/0200020A.jpg) - -Once created, you can consider these widgets as elementary objects even -though they are compound ones. The pictures above present four different -layouts of five buttons. The first one shows laid out vertically -buttons. Almost everywhere you can find this vertical orientation. -Looking at dialogs you see that often they consist of number of rows -laid out below each other. Some of the rows could have an internal -vertical structure as well. The second picture shows the same buttons -laid out horizontally - the next common orientation. The other two show -different layouts based on mixed use of the vertical and horizontal -orientation. You might recognize their pattern: two (third picture) and -three (last picture) rows that are vertically laid out. - -As we already explained the layout process is always applying to a -container. It will be enough to define the container frame with vertical -or horizontal layout to have buttons as in the first and second -pictures. - -To design them in several rows we need to use additional frames as -invisible containers: two horizontal frames, children of a vertical -parent frame; or one horizontal frame laid out vertically with the Draw -and Exit buttons. For widgets in a group it is obvious to use a vertical -layout. - -The layout hints data member of **`TGLayoutHints`** is the bit wise OR -between the hints: - -+------------------+---------------------------------------------------------+ -| Hints | Description | -+------------------+---------------------------------------------------------+ -| `kLHintsNoHints` | no specified layout hints, the default ones will be | -| | used | -+------------------+---------------------------------------------------------+ -| `kLHintsLeft` | specifies the frame position to the left of the | -| | container frame after other frames with the same hint | -| | into the list | -+------------------+---------------------------------------------------------+ -| `kLHintsCenterX` | specifies the frame position centered horizontally | -| | (with vertical containers only) | -+------------------+---------------------------------------------------------+ -| `kLHintsRight` | specifies the frame position to the right of the | -| | container frame before any other laid out frames with | -| | the same hint into the list | -+------------------+---------------------------------------------------------+ -| `kLHintsTop` | specifies the frame position to the top of the | -| | container frame, below any laid out frames with the | -| | same hint | -+------------------+---------------------------------------------------------+ -| `kLHintsCenterY` | specifies the frame position centered vertically (with | -| | horizontal containers only) | -+------------------+---------------------------------------------------------+ -| `kLHintsBottom` | specifies the frame position to the bottom of the | -| | container frame, above any laid out frames with the | -| | same hint | -+------------------+---------------------------------------------------------+ -| `kLHintsExpandX` | specifies the frame to be expanded up to the width of | -| | the container frame. If the container frame is a | -| | vertical frame - it will fit the whole width. If it is | -| | a horizontal frame - after the positioning of all | -| | frames the available "free" width space is shared | -| | between the frames having this hint | -+------------------+---------------------------------------------------------+ -| `kLHintsExpandY` | specifies the frame to be expanded up to the height of | -| | the container frame. If the container frame is a | -| | horizontal frame - it will fit the whole height. If the | -| | container frame is a vertical frame - after the | -| | arrangement of all frames the available "free" height | -| | space is shared between the frames having this hint | -+------------------+---------------------------------------------------------+ -| `kLHintsNormal` | = `kLHintsLeft | kLHintsTop` - default hints | -+------------------+---------------------------------------------------------+ - -Layout policy: - -Child frames never modify their container frame. The container frame can -(or cannot) adapt its size in the layout process. It can show all or a -part of its frames. Every **`TGFrame`** object has a default minimum -size (1, 1) assured by **`TGWindow`**. - -## Event Processing: Signals and Slots - - -Event handling covers the interaction between different objects and -between the user and the objects in an application. There are two -general ways for the user to interact with an application: the keyboard -and the mouse. The Graphical User Interface is as a bridge between the -user and the program - it provides methods to detect the user actions -and instruments that do something as a reaction of these actions. The -user communicates with an application through the window system. The -window system reports interaction events to the application. The -application in turn forwards them to the currently active window. The -objects/widgets receive the events and react to them according to the -application functionality. - -![](pictures/0200020B.jpg) - -The signals/slot communication mechanism is an advanced object -communication concept; it largely replaces the concept of callback -functions to handle actions in GUI's. Signals and slots are just like -any object-oriented methods implemented in C++. The objects are the -instances of classes that don't know anything about each other. They -interact and allow method calls of other object's methods. The idea is -simple: any object can send out (emit) a signal in certain situations -saying that something happened. This is all it does to communicate and -it does not know whether anything is interested in this information. On -the other side there might be an object waiting for that signal and -ready to react to it. This object disposes of special instruments to -listen to the sent out signals. To have a communication we need a -message transmission between the objects. In this simple example we use -signals and slots. The code of the method **`TGButton::Clicked()`** is: - -``` {.cpp} -virtual void Clicked() { Emit("Clicked()"); } // *SIGNAL* -``` - -I.e. any button emits the signal `Clicked()` any time someone clicks on -it. As you can see this method is virtual and could be overridden if you -need to. In our simple example we call the `Connect()` method to connect -the `Clicked()` signal of Draw button with `MyMainFrame::DoDraw():` - -``` {.cpp} -draw->Connect("Clicked()","MyMainFrame",this,"DoDraw()"); -``` - -In the same way we can connect to the signal `Clicked()` of the Exit -button with the system call `gApplication->Terminate(0).` We declare a -new slot `DoExit(),` implement it to invoke the termination call and -associate this slot with the signal `Clicked()` of the Exit button. - -The code of `example.C` can be changed as follows: - -``` {.cpp} -public: -... - void DoExit(); // a new slot is added -} -void MyMainFrame::DoExit() { - gApplication->Terminate(0); -} -MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) { -... - TGTextButton *exit = new TGTextButton(hframe,"&Exit "); - // connects signal Clicked() with slot DoExit() - exit->Connect("Clicked()","MyMainFrame",this,"DoExit()"); -... -} -``` - -Here is an abstract view of the signal/slots connections in `example.C`: - -![](pictures/0200020C.jpg) - -To benefit from this mechanism your classes must inherit from -**`TQObject`** or otherwise the class definition must start with -`RQ_OBJECT("ClassName") `macro. This macro allows the signals/slots -communication mechanism to be applied between compiled and interpreted -classes in an interactive ROOT session without having the class derive -from **`TQObject`**. Every signal method declaration is followed by a -comment `"*SIGNAL*".` Only instances of a class that defines a signal or -instances of its subclasses can emit the signal. The ROOT implementation -of a popular example presenting signals and slots is the next. Let's -have a minimal class declaration: - -``` {.cpp} -class MyClass { -private: - Int_t fValue; -public: - MyClass() { fValue=0; } - Int_t GetValue() const { return fValue; } - void SetValue(Int_t); -}; -``` - -It will become the following as interpreted: - -``` {.cpp} -class MyClass { - RQ_OBJECT("MyClass") -private: - Int_t fValue; -public: - MyClass() { fValue=0; } - Int_t GetValue() const { return fValue; } - void SetValue(Int_t); // *SIGNAL* -}; -``` - -Both class declarations have the same data member and public methods to -access the value. By placing the `RQ_OBJECT("MyClass")` macro inside the -`MyClass` body (`MyClass` is not inherited from **`TQObject`**) we allow -this class to use the signal/slot communication. Any instance of this -class can tell the outside world that the state of its data member has -changed by emitting a signal `SetValue(Int_t).` A possible -implementation of `MyClass::SetValue()` can be: - -``` {.cpp} -void MyClass::SetValue(Int_t v) { - if (v != fValue) { - fValue = v; - Emit("SetValue(Int_t)",v); - } -} -``` - -The line `Emit("SetValue(Int_t)",v)` activates the signal -`SetValue(Int_t)` with argument v. You can use any of the methods -**`TQObject::Emit("full_method_name",arguments)`** to emit a signal. We -create two instances of `MyClass` and connect them together: - -``` {.cpp} -MyClass *objA = new MyClass(); -MyClass *objB = new MyClass(); -objA->Connect("SetValue(Int_t)","MyClass",objB,"SetValue(Int_t)"); -objB->SetValue(11); -objA->SetValue(79); -objB->GetValue(); // the value is 79 -``` - -By calling the method `objA->Connect()`, `objA` connects its signal -"`SetValue(Int_t)`" to the "`MyClass::SetValue(Int_t)`" method (slot) of -`objB`. Next, when you call `objA->SetValue(79) `object `objA `emits a -signal which `objB `receives and `objB->SetValue(79) `is invoked. - -It is executed immediately, just like a normal function call. `objB` -will emit the same signal in turn, but nobody is interested in this -signal, since no slot has been connected to it. Signals are currently -implemented for all ROOT GUI classes, event handlers -(**`TFileHandler`**, **`TSignalHandler`**, etc.), timers (**`TTimer)`** -and pads (**`TPad`**, **`TCanvas`**, etc.). To find all defined signals -you just do: `grep ‘*SIGNAL*' $ROOTSYS/include/*.h` - -As a programmer you build the sender-receiver part of object connections -using the `TQObject::Connect()` method. You can connect one signal to -many different slots. The slots will be activated in order they were -connected to the signal. You can change this order using the methods -`LowPriority()` and `HightPriority()` of **`TQObject`**. Also, many -signals can be connected to one slot of a particular object or a slot -can be connected to a signal for all objects of a specific class. It is -even possible to connect a signal directly to another signal - this will -emit the second signal immediately after the first one is emitted. - -All signals and slots are normal class methods and can take any number -of arguments of any type. The common methods of **`TQObject`** that -activate a signal with any number and type of parameters are: - -``` {.cpp} -Emit(signal_name,param); -``` - -With no parameters `param` the method will be: - -``` {.cpp} -ApplyButton->Emit("Clicked()"); -``` - -`param` can be a single parameter or an array of `Long_t` parameters as -it is shown below: - -``` {.cpp} -TQObject *processor; // data processor -TH1F *hist; // filled with processor results -... -processor->Connect("Evaluated(Float_t, Float_t)", "TH1F", hist, - "Fill(Axis_t x, Axis_t y)"); -... -Longptr_t args[2]; -args[0]=(Longptr_t)processor->GetValue(1); -args[1]=(Longptr_t)processor->GetValue(2); -... -processor->Emit("Evaluated(Float_t, Float_t)", args); -... -``` - -To use signals and slot you need something that brings them together. -The class **`TQObject`** has several methods creating sender-receiver -connections. Some of them are static and can be called without having an -instance of the class. The ROOT implementation of signals and slots -allows connections to any known Cling object. The class name parameter in -the `Connect()` methods must be a class with a dictionary (interpreted -classes have an implicit dictionary). - -``` {.cpp} -TGButton *button; -TH2 *hist; -... -TQObject::Connect(button,"Clicked()","TH2",hist,"Draw(Option_t*)"); -``` - -You can replace it with 0 (zero) and in this case the slot string -defines a global or interpreted function name. The receiver parameter -should be zero too. For example: - -``` {.cpp} -TQObject::Connect(button, "Clicked()",0,0, "hsimple()"); -``` - -To make a single connection from all objects of a class you should -write: - -``` {.cpp} -TQObject::Connect("Channel", "AllarmOn()","HandlerClass",handler, - "HandleAllarm()"); -``` - -The first argument specifies the class name Channel. The signal -`AllarmOn()` of any object of the class Channel is connected to the -`HandleAllarm()` method of the handler object of the class -`HandlerClass`. - -In `example.C` we have used the not-static `Connect() `method: - -``` {.cpp} -Bool_t Connect(const char *signal, const char *receiver_class, - void *receiver, const char *slot); -``` - -It needs to know four things: the signal that should be connected, the -receiver class, the object that will receive the signal, and the slot -that will be connected to the signal. Because this method is non-static -we can write this as a receiver parameter. - -In all methods you have to specify the signal and the slot with their -names and parameter types. Do not write values instead of types in that -place. It is possible to pass a parameter by value to a slot method in -the following way: - -``` {.cpp} -Connect(myButton, "Pressed()", "TH1", hist, "SetMaximum(=123) "); -Connect(myButton, "Pressed()", "TH1", hist, "Draw(=\"LEGO\")"); -``` - -As you see the parameter's value is preceded by the equation symbol (=). -Please note that this method of passing arguments by value works only -if the signal has less arguments than the slot. -If the signal method has the same number of arguments, then the slot -argument will be overwritten with the signal argument. In the -example below, the Draw option would be overwritten in the first line -by the emitted signal argument. The second line would be ok, the -argument passed by value would not be overwritten. - -``` {.cpp} -Connect(myComboBox, "Selected(const char*)", "TTree", myTree, "Draw(=\"x\")"); -Connect(myComboBox, "Selected(const char*)", "TTree", myTree, "Draw(const char*, =\" y==1 \")"); -``` - -In addition, if the signal and slot arguments differ in argument type, -passing arguments by value leads to undefined behaviour and illegal -memory access, as the signal argument will be casted to another data -type. In the example below, if Selected emits Int_t = 1, then ChangeText -will try to read a TString at address 0x1. - -``` {.cpp} -Connect(myComboBox, "Selected(Int_t)", "TGTextButton", myButton, "ChangeText(=\"Hello\")"); -``` - -You have the possibility to destroy a signal/slot connection by using -`Disconnect()` methods. There are three ways to do this: - -1/ to destroy all connections to an object's signals; - -2/ to destroy all connections to a particular object's signal; 3/ to -detach an object from a specific receiver: - -``` {.cpp} -Disconnect(myObgect); // case 1 -Disconnect(myObgect, "mySignal"); // case 2 -Disconnect(myObgect,0,myReceiver,0); // case 3 -``` - -Three parameters of these methods could be replaced by 0. The meaning in -these cases would be "any signal", "any receiving object", "any slot of -the receiving object", i.e. 0 is used as a wildcard. The sender -parameter cannot be 0, because you can disconnect signals from one given -object. If the signal parameter is 0, the receiver and the slot are -disconnected from any signal. Giving the name of the signal you -disconnect this signal. - -In addition to all Qt features the ROOT version of signals/slots gives -you the possibility to connect slots to a class. The slots will be -executed every time the specified signal is emitted by any object of -this class. A slot can have default arguments and it can be either a -class method or stand-alone function (compiled or interpreted). - -The method `TQObject::HasConnection(signale_name)` checks if there is an -object connected to this signal and returns true if it is the case. - -Using `TQObject::NumberOfConnections()`, -**`TQObject`**`::NumberOfSignals()` you can check how many signals or -connections has the object. - -The rules for using signals/slots mechanism in a standalone executable -program do not differ from what was described previously. Let's remind -that - -- a slot can be any class method with a generated Cling dictionary - -- a slot can be a function with a dictionary - -Detailed information how to generate a dictionary can be found on - - -The following example demonstrates how to use signals/slots mechanism in -a standalone executable program on `linux` platform with the `gcc` -compiler. - -`tst.C ` - -``` {.cpp} -#include -#include - -class A { - RQ_OBJECT("A") -private: - Int_t fValue; -public: - A() : fValue(0) { } - ~A() { } - void SetValue(Int_t value); // *SIGNAL* - void PrintValue() const { printf("value = %d\n", fValue); } -}; -void A::SetValue(Int_t value) { // Set new value - // Emit signal "SetValue(Int_t)" with a single parameter - if (value != fValue) { - fValue = value; - Emit("SetValue(Int_t)", fValue); - } -} -// Main program -#ifdef STANDALONE -int main(int argc, char **argv) { - A* a = new A(); - A* b = new A(); - a->Connect("SetValue(Int_t)", "A", b, "SetValue(Int_t)"); - printf("n******* Test of SetValue(Int_t) signal *******n"); - b->SetValue(10); - printf("nt***** b before ******n"); - b->PrintValue(); - a->SetValue(20); - printf("t***** b after a->SetValue(20) ******n"); - b->PrintValue(); - return 0; -} -#endif -``` - -ACLiC simplifies this procedure and allows the dictionary generation by: - -``` {.cpp} -root[] .L tst.C++ -``` - -It will create the shared library `tst_C.so.` - -The next line will create an executable: - -**`` g++ -otst tst.C `root-config --cflags --libs` ./tst_C.so -DSTANDALONE ``** - -The library `tst_C.so` is a dynamically loaded library and should be -located in `$LD_LIBRARY_PATH`. The current working directory should be -added to `$LD_LIBRARY_PATH` via: - -**`export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./`** - -To run it, you just do: - -**`./tst`** - -## Widgets in Detail - - -### Buttons - - -Buttons are a popular group of widgets designed to provide specific -interfaces for user interaction. **`TGButton`** is an abstract class -defining the general button behavior: width, height, state, its group, -tool tip text, etc. - -There are two main groups of buttons: command buttons with a text or -graphics inside that indicate the action to be accomplished and option -buttons well known as radio and check buttons that select or change -properties. The first group is presented in ROOT by -**`TGPictureButton`** and **`TGTextButton`** classes. They yield an -action as soon as they are clicked. It can be opening/closing a dialog -box or invoking a specific function in an application. Remember the Draw -button from the example. The radio and check buttons from the second -group are used to select an option. There is a visual difference between -these two groups: the text buttons appear "pressed in" only while they -are clicked, while the radio and check buttons change their appearance -when they are selected and keep that appearance afterwards. - -A text button is represented by the class **`TGTextButton`**. We already -used its constructor in the example. The button label indicates the -action to be taken when the button is selected or pressed. The text can -be a hot string defining a hot key (known as shortcut key also) for this -selection. The hot key is an underlined character in a button label that -shows the assigned keyboard mnemonic for its choice. A button that -prompts more information for users has the label generally followed by -ellipsis (...). - -![](pictures/0300020D.png) - -As we saw the hot strings "&Draw" and "&Exit" define the text labels -"Draw" and "Exit" and keyboard mnemonics `Alt+D`, `Alt+E` for their -selection. The letter D and E appear underlined on the screen. All text -buttons should have a unique shortcut key with the exception of OK and -Cancel. - -These buttons are usually placed within a window to provide fast access -to frequently used or critical commands. They help in situations where a -command is not available through the menu bar. You already know that a -command string can be passed in the text button via the constructor: - -``` {.cpp} -TGTextButton(const TGWindow *p, const char *s, const char *cmd, - Int_t id, GContext_t norm, FontStruct_t font, - UInt_t options); -``` - -A button label can be changed by `SetText(new_label).` There are -important guidelines to be followed about a button label. The text has -to provide a meaningful description of the performed action. The -single-word label should be used whenever possible, only two-three words -for clarity, if necessary. Do not number labels. Always follow all -platform presentation and usage guidelines for standard button -functions. Let's remember a few standard names and definitions of well -known buttons: - -***`OK`*** - any changed information in a window is accepted and the -window is closed; - -***`Cancel`*** - closes window without implementing submitted changes; - -***`Reset `***- resets defaults and cancels any changed information that -has not be submitted; - -***`Apply`*** - any changed information is accepted and again displayed -in the window that remains open; - -***`Close`*** - closes the window; - -***`Help`*** - opens online Help. - -Below are examples of text buttons. Note the two placement methods. The -first example should be used when there are one to three command -buttons; the second one when there are more than three buttons. - -![](pictures/0200020E.jpg) - -Picture buttons are usually rectangular in shape with an icon or -graphics label. These buttons may appear alone or placed in a group at -the window's top or side. They are most frequently used to quickly -access commands, many of which are normally accessed through the tool -bar. For example, the picture buttons below can be used to provide -different styles of a histogram drawing. - -![](pictures/0200020F.jpg) - -Here is the example how to create the first button: - -``` {.cpp} -TGPictureButton *fPicture = new TGPictureButton(parent, - gClient->GetPicture("h1_s.xpm"), 11); -``` - -The picture of file h1\_s.xpm is used in the button. All `.xpm` files -are located in the directory `$ROOTSYS/icons`. You can assign a command -directly as a parameter of the picture button constructor. The picture -of **`TGPictureButton`** can be changed by: - -``` {.cpp} -fPicture->SetPicture("h2_s.xpm"); -``` - -The advantage of command buttons is that they are always visible, -providing a reminder of their existence. They can be inscribed with a -meaningful description of what they do by -`TGToolTip("Some describing text").` Their activation is much easier and -faster than using a two-step menu bar/pull-down sequence. The only -disadvantage of the text and picture buttons is that they consume -considerable screen space if they are many. Having no more than six -command buttons per window or dialog box helps to appropriately balance -the application's effectiveness, its real efficiency, and the -operational simplicity. - -The classes **`TGRadioButton`** and **`TGCheckButton`** present the -option buttons in ROOT. Like the text buttons, they have text or hot -string as a label. Radio buttons are grouped in logical sets of two or -more and appear with a text label to the right. The choices are mutually -exclusive and only one setting is permitted at one time. They represent -visually all alternatives and it is easy to access and compare choices. -They facilitate the situations where all alternatives cannot be easily -remembered or where displaying the alternatives together helps to -understand and select the proper choice. It is very useful to provide a -default setting whenever it is possible. When it is not possible to -establish a default setting because of the nature of the information, it -is better to leave all radio buttons blank. - -![](pictures/03000210.png) - -A columnar orientation is the preferred manner of radio buttons -presentation. If the vertical space on the window is limited, they can -be oriented horizontally. Selection choices should be organized -logically in groups. Here is the example that produces the image above: - -``` {.cpp} -br = new TGButtonGroup(p,"Coordinate system",kVerticalFrame); -fR[0] = new TGRadioButton(bg,new TGHotString("&Pixel")); -fR[1] = new TGRadioButton(bg,new TGHotString("&NDC ")); -fR[2] = new TGRadioButton(bg,new TGHotString("&User ")); -fR[1]->SetState(kButtonDown); -br->Show(); -``` - -It is enough to change `kVerticalFrame` to `kHorizontalFrame` in -**`TGButtonGroup`** constructor and you will have radio buttons aligned -horizontally: - -![](pictures/03000211.png) - -The class **`TGButtonGroup`** will help you to organize button widgets -in a group. There is no need to call `AddFrame()` since the buttons are -added automatically with a default layout hint to their parent by -**`TGButtonGroup`**`::Show()` as shown in the previous example. The -buttons in the group have assigned identifiers. Any button in a group -emits a `Clicked()` signal with this identifier when it is clicked. This -giving an ideal solution to connect several `Clicked()` signals to one -slot. - -An exclusive button group switches off all toggle buttons except the -selected one. The group is by default non-exclusive but its entire radio -buttons will be mutually exclusive. - -**`TGHButtonGroup`** and **`TGVButtonGroup`** are convenience classes -that offer you a thin layer on top of **`TGButtonGroup`**. -**`TGHButtonGroup`** organize button widgets in a group of one -horizontal row, **`TGVButtonGroup`** in a group of one column. You can -also organize buttons in rows and columns using the provided constructor -and **`TGMatrixLayout`**. - -Do not use a radio button to indicate the presence or absence of a state -- use a check box instead. - -![](pictures/03000212.png) - -To have the check button "Event Status" and to set it as selected we -need to write: - -``` {.cpp} -TGCheckButton *estat = new TGCheckButton(p, "Event Status",1); -estat->SetState(kButtonDown); -``` - -Check boxes show the selected choices and any number of them can be -selected, including none. Their proper usage is for setting attributes, -properties or values; also for data or choices that are discrete, small -and fixed in number, not easily remembered. With check boxes all -alternatives are visible: it is easy to access and compare choices -because they can all be seen together. Each option acts as a switch and -can be either "on" or "off". It is never changed in contents. Checkboxes -differ from radio buttons in that they permit selection of more than one -alternative. Each box can be switched on or off independently. These -buttons can be used alone or grouped in sets. It is good practice to -provide default settings for check boxes whenever it is possible. - -![](pictures/03000213.png) - -This can be done by: - -``` {.cpp} -SetState(EButtonState state) -``` - -The parameter state can be one of `kButtonUp`, `kButtonDown`, -`kButtonEngaged`, `kButtonDisabled`. - -Check boxes can be used to affect other controls. The contents of a list -can, for example, be filtered by setting a check box. In any case, use a -check box only when both states of a choice are clearly opposite and -unambiguous. If opposite states are not clear, it is better to use two -radio buttons. - -Choice description, i.e. check box label, must be clear, meaningful, -fully spelled out, and displayed in mixed-type text. Whenever the use of -a given button is inappropriate, for whatever reason, that button should -be disabled: - -``` {.cpp} -button->SetState(kButtonDisabled); -``` - -Never make a button appear and disappear. - -In general, option buttons should not offer more than eight choices. If -the number of choices exceeds this maximum, it is better to use a -multiple selection list box. - -The method `IsToggleButton()` gives the information whether a radio -button or a check button is selected. An option button can be set or -unset via its method `PSetState(EButtonState state).` - -The method `HandleKey(event)` is called when the defined hotkey is hit -for any button. It sets the selected option button or clicks the -selected text button and invokes its defined action. - -### Text Entries - - -A **`TGTextEntry`** is a one-line text input widget. It contains text -that is entered or modified through the keyboard. This text may be -displayed in different way according to the set echo mode. Users can -control them by` SetEchoMode()`, `GetEchoMode()` methods. - -- `kNormal` - display characters as they are entered (default); - -- `kNoEcho` - do not display anything; - -- `kPassword` - display asterisks instead of the characters actually - entered. - -The way in which typed characters are inserted in the text entry is -defined by `TGTextEntry::EInsertMode` and can be toggled by the Insert -key: - -- `kInsert` - typed character are inserted (cursor has shape of short - line) - -- `kReplace` - entered characters substitute already typed ones - (cursor has the shape of filled rectangle). - -![](pictures/03000214.png) ![](pictures/03000215.png) - -There ate different text alignment modes defined by -`TGWidget::ETextJustification`. They are valid until text fits the frame -width of the text entry field. - -- `kTextLeft` - left-side text alignment - -- `kTextRight` - right-side text alignment - -- `kTextCenterX` - center text alignment along x direction - -- `kTextTop` - top-side text alignment - -- `kTextBottom` - bottom-side text alignment - -- `kTextCenterY` - center text alignment along y direction - -### Number Entries - - -The **`TGNumberEntry`** class present number entry widgets. A number -entry is a single-line field followed by two small, vertically arranged -up-down buttons. Its purpose is to make a selection by either scrolling -through a small set of meaningful predefined choices or typing numbers. -The **`TGNumberFormat`** class contains `enum` types to specify the -numeric format. The number entry widget is based on -**`TGTextEntry`**. It allows only numerical input. The widget supports -numerous formats including integers, hex numbers, real numbers, fixed -fraction real and time/date formats. It also allows to restrict input -values to non-negative or positive numbers and to specify explicit -limits. - -![](pictures/03000216.png) - -The following styles are supported: - -- `kNESInteger` - integer number - -- `kNESRealOne` - real number with one digit (no exponent) - -- `kNESRealTwo` - real number with two digits (no exponent) - -- `kNESRealThree` - real number with three digits (no exponent) - -- `kNESRealFour` - real number with four digits (no exponent) - -- `kNESReal` - arbitrary real number - -- `kNESDegree` - angle in degree:minutes:seconds format - -- `kNESMinSec` - time in minutes:seconds format - -- `kNESMinSecCent` - time in minutes:seconds.centiseconds format - -- `kNESHourMin` - time in hour:minutes format - -- `kNESHourMinSec` - time in hour:minutes:seconds format - -- `kNESDayMYear` - date in day/month/year format - -- `kNESMDayYear` - date in month/day/year format - -- `kNESHex`- hexadecimal number - -The following attributes can be specified: - -- `kNEAAnyNumber` - any number is allowed - -- `kNEANonNegative` - only non-negative numbers are allowed - -- `kNEAPositive` - only positive numbers are allowed - -Explicit limits can be specified individually: - -- `kNELNoLimits` - no limits - -- `kNELLimitMin` - lower limit only - -- `kNELLimitMax` - upper limit only - -- `kNELLimitMinMax` - both lower and upper limits - -``` {.cpp} -fN1 = new TGNumberEntry(parent, 0.005, 9, kENTRY1, - TGNumberFormat::kNESRealThree, //style - TGNumberFormat::kNEAAnyNumber, //input value filter - TGNumberFormat::kNELLimitMinMax, //specify limits - -1.,1.); //limit values -``` - -**`TGNumberEntryField`** is a number entry input widget. - -``` {.cpp} -Nent = new TGNumberEntryField(hgrunf2, kNENT_ID, 0.6, - TGNumberFormat::kNESRealThree, - TGNumberFormat::kNEAAnyNumber); -``` - -**`TGNumberEntryField`** is a plain vanilla entry field, whereas -**`TGNumberEntry`** adds two small buttons to increase and decrease the -numerical value in the field. The number entry widgets also support -using the up and down cursor keys to change the numerical values. The -step size can be selected with control and shift keys: - -- --small step (1 unit/factor of 3) - -- Shift medium step (10 units/factor of 10) - -- Controllarge step (100 units/factor of 30) - -- Shift+Controlhuge step (1000 units/factor of 100) - -The steps are either linear or logarithmic. The default behavior is set -when the entry field is created, but it can be changed by pressing the -alt key at the same time. - -### Menus - - -Menus provide a list of commands or options helping the user to select -and to perform a task. The menu system classes are **`TGMenuBar`**, -**`TGMenuTitle`**, **`TGPopupMenu`**, and **`TGMenuEntry`**. - -The **`TGMenuBar`** class implements a menu bar widget. It is used to -specify and provide access to common and frequently used application -actions described in menu titles, implemented by **`TGMenuTitle`** -class. The menu bar is the highest-level of the menu system and it is a -starting point for all interactions. Also, it is always visible and -allows using the keyboard equivalents. The geometry of the menu bar is -automatically set to the parent widget, i.e. the menu bar automatically -resizes itself so that it has the same width as its parent (typically -**`TGMainFrame`**). - -The menu bar is as a container for its menus - objects of the type -**`TGPopupMenu.`** Popup menus can appear in a menu bar. They can be a -sub-menu of another popup menu (cascading menus) or can be standalone -(as a context menu). They are made of one or more menu items choices. -When displayed, the menu items are arranged in a vertical list. Usually -they correspond to actions (e.g. `Open`**)**. These items can be labeled -with text, graphics or a combination of both. Each of them should have a -character defined as its unique key for access. Grouped logically by -their functionality, they are separated visually by menu separators in -groups. For example, The `File` menu is a common menu title for tasks -that apply to a file, as **`Open`**,**`Save`**,**`Close`**,**`Print`**... - -``` {.cpp} -// a popup menu -fMenuFile = new TGPopupMenu(gClient->GetRoot()); - -// adding menu entries -fMenuFile->AddEntry("&Open...",M_FILE_OPEN); -fMenuFile->AddEntry("&Save",M_FILE_SAVE); -fMenuFile->AddEntry("S&ave as...",M_FILE_SAVEAS); -fMenuFile->AddEntry("&Close", -1); - -// adding separator -fMenuFile->AddSeparator(); - -// next group of menu entries -fMenuFile->AddEntry("&Print",M_FILE_PRINT); -fMenuFile->AddEntry("P&rint setup...",M_FILE_PRINTSETUP); -. . . -fMenuFile->AddSeparator(); -fMenuFile->AddEntry("E&xit",M_FILE_EXIT); -``` - -First we create the File menu by creating an object of -class**` TGPopupMenu`** and adding menu entries with `AddEntry` method. -Its first parameter is a hot string, the second - a menu ID. The -ampersand character (&) denotes shortcut for each menu entry; you can -use the letter after it to manage the menu via keyboard. There are three -groups of menu entries separated visually by two separators. - -You can add a sub-menu by using the method `TGPopupMenu::AddPopup`. Its -first parameter is again a string, the second one - a pointer to a -**`TGPopupMenu`** object that will appear as a sub-menu when the menu -entry will be selected. The often used visual indicator of a sub- menu -is a right-facing arrow to the right of the parent menu item. Generally -only one level of cascading menus is recommended and you should be -careful in using more. Next lines show how to create a menu bar with -`File`**,**`Test` and `Help` menus: - -``` {.cpp} -// menu bar item layout hints -fMBItemLayout = new TGLayoutHints(kLHintsTop|kLHintsLeft,0,4,0,0); -fMBHelpLayout = new TGLayoutHints(kLHintsTop|kLHintsRight); - -// menu bar -fMenuBar = new TGMenuBar(fMain,100,20,kHorizontalFrame); - -// adding popup menus -fMenuBar->AddPopup("&File", fMenuFile, fMBItemLayout); -fMenuBar->AddPopup("&Test", fMenuTest, fMBItemLayout); -fMenuBar->AddPopup("&Help", fMenuHelp, fMBHelpLayout); -``` - -Using the method `TGMenuBar::AddPopup` we add three **`TGPopupMenu`** -objects to the menu bar `fMenuBar`. The first parameter is a hot string -used by **`TGMenuTitle`** object. When you add a popup menu to the menu -bar, a **`TGMenuTitle`** object is created by the menu bar. It is the -name of the popup menu. A menu title should have a one-word name that -reflects the purpose of all items within the corresponding popup menu. -It should also have a defined character as its unique access key. The -second parameter is the popup menu we would like to add. The third one -is an object of **`TGLayoutHints`** type that defines how the menu title -will be laid out in the menu bar. In our example the *`File`* and `Test` -menus will be laid out to the left of the menu bar with 4 pixels -distance in between, the `Help` menu - will be laid out to the right. - -The menu classes provide a very flexible menu system: you can enable, -disable, add or remove menu items dynamically. The method -`HideEntry(menuID)` hides the menu entry (the entry will not be shown in -the popup menu). To enable a hidden entry you should call -`EnableEntry(menuID)` method. By default all entries are enabled. The -method `DisableEntry(menuID)` helps you to disable a menu entry - it -will appear in sunken relieve. The `DeleteEntry(menuID)` method will -delete the specified entry from the menu. - -A few words about the menu design. A menu should be kept consistent and -simple. All related items need to be in a popup menu. The cascade menus -should be used judiciously. Try to limit them to one, maximum two -levels. - -There are some rules for naming the menu objects: - -- Define unique names within a menu - -- Use capitalized one-word names allowing the quick scan of the menu - -- Define unique access key for any menu item - -- Indicate by ellipsis (...) after the title with no space when a menu - item will pop-up a dialog box - -The proper kind of graphical menus is a critical point to every -application success and depends of three main factors: - -- number of presented items in the menu - -- how often the menu is used - -- how often the menu contents may change - -### Toolbar - - -![](pictures/03000217.png) - -A toolbar (**`TGToolBar`**) is a composite frame that contains -**`TGPictureButton `**objects. It provides an easy and fast access to -most frequently used commands or options across multiple application -screens. Also, it invokes easily a sub application within an -application. All its functions can be obtained by application menus. It -is located horizontally at the top of the main window just below the -menu bar. All other subtask and sub-feature bars are positioned along -sides of window. - -``` {.cpp} -// toolbar icon files -const char *xpms[] = { - "x_pic.xpm", - "y_pic.xpm", - "z_pic.xpm", - 0 -}; -// toolbar tool tip text -const char *tips[] = { - "X Settings", - "Y Settings", - "Z Settings", - 0 -}; -// toolbar button separator -int separator = 5; - -// structure containing toolbar button information -ToolBarData_t t[3]; - -// creation of a toolbar object as a child of main frame -TGToolBar *tb = new TGToolBar(fMain,520,80); - -for (int i = 0; i < 3; i++) { - // filling the ToolBarData_t with information - t[i].fPixmap = xpms[i]; // icon file - t[i].fTipText = tips[i]; // tool tip text - t[i].fStayDown = kFALSE; // button behavior if clicked - t[i].fId = i+1; // button id - t[i].fButton = NULL; // button pointer - - if (strlen(xpms[i]) == 0) { - separator = 5; - continue; - } - tb->AddButton(fMain,&t[i],separator); - separator = 0; -} -// adding the tool bar to the main frame -fMain->AddFrame(tb, new TGLayoutHints(kLHintsTop|kLHintsExpandX)); - -// adding a horizontal line as a separator -TGHorizontal3DLine *lh = new TGHorizontal3DLine(fMain); -fMain->AddFrame(lh, new TGLayoutHints(kLHintsTop|kLHintsExpandX)); -``` - -To have a tool bar in your application you do not need to do anything -special - only to create objects: a tool bar and its picture buttons. -This sample code creates the following three toolbar buttons: - -![](pictures/03000218.png) - -First we need to complete a `ToolBarData_t` structure for each tool bar -button before adding it to the tool bar. This structure contains: - -- the icon file name "`filename.xpm`" - -- the tool tip text - a short help message explaining the button - purpose - -- the Boolean variable defining the button behavior when is clicked - -- `kFALSE` - do not stay down - -- `kTRUE` - to stay down - -- the button ID - -- the button pointer (**`TGButton *`**) - should be `NULL` - -We create an array `*xpms[]` containing the icon file names that will be -used for a picture button creation. If you write only the file names -here ROOT will search these files in `$ROOTSYS/icons` directory. If the -icon files are not there, you should provide the full path name also. -The array `*tips[] `contains the tool tip texts for buttons. The integer -variable separator is used to set the distance between two groups of -toolbar buttons. It defines the amount of pixels to the left for each -button. - -We create a tool bar object and add the buttons using the `AddButton` -method. The variable separator helps us to define no space between the -buttons in a group (0), and 5 pixels extra-space before and after. All -buttons added via this method will be deleted by the toolbar. On return -the **`TGButton`** field of the `ToolBarData_t` structure is filled in -(if the icon pixmap was valid). The first parameter is the window to -which the button messages will be sent. Lastly, we create an object of -class **`TGHorizontal3DLine`** - a horizontal 3D line. It will separate -the toolbar from the menu bar because the layout hints we define as -`kLHintsTop` | `kLHintsExpandX`. - -It is user friendly to allow the possibility for the tool bar to be -turned on or off (via a menu). If you use a single tool bar, it should -fill the complete width of its parent. When using more than one, you -should also think about setting the bar size to the end of the most -right button. This way other bars can be displayed in the same row below -the menu bar. - -Tool bar buttons should have equal size, meaningful and unique icons, -and short meaningful tool tip text. The related buttons should be -grouped together by frequency or sequence of use, or importance. -Potentially destructive buttons must be separated from them to avoid -accidental activation and potentially catastrophic results. Temporarily -not available items should be displayed grayed out. - -### List Boxes - - -The purpose of a list box is to display a collection of items from which -single or multiple selection can be made. It is always visible, having a -scroll bar when the displayed area is not enough to show all items. The -choices may be mutually exclusive (a list box with single selection) or -not mutually exclusive (a list box with multiple selection). - -![](pictures/02000219.jpg) - -The proper usage of the list boxes is for selecting values, or objects, -or setting attributes. You have to create them to display 4 to 8 choices -at one time (3 is a required minimum in case of lack of screen space). -The list should contain not more than 40 items accessible by scrolling -view (vertical scroll bar). If more are required, you should provide a -method for using search criteria or scoping the options. The best list -boxes use is for textual data or choices. They should be wide enough to -display fully all items. When it is not possible, break the long items -with ellipsis and provide tool tip that displays the full item text. - -The list box widget is represented by **`TGListBox`**, -**`TGLBContainer`**, **`TGLBEntry`** and **`TGTextLBEntry`** classes. -Currently entries are simple text strings (**`TGTextLBEntry`**). A -**`TGListBox`** looks a lot like a **`TGCanvas`**. It has a -**`TGViewPort`** containing a **`TGLBContainer`** which contains the -entries and it also has a vertical scrollbar which becomes visible if -there are more items than fit in the visible part of the container. The -**`TGListBox`** is user callable. The other classes are service classes -of the list box. Here is a sample code showing how to create a list box -with ten entries: - -``` {.cpp} -// list box widget containing 10 entries -int fFirstEntry = 0, fLastEntry = 10; -char tmp[20]; -TGListBox *fListBox = new TGListBox(parent, 90); -for (i = fFirstEntry; i < fLastEntry; i++) { - sprintf(tmp, "Entry %i", i+1); - fListBox->AddEntry(tmp, i); -} -fListBox->Resize(150, 80); -parent->AddFrame(fListBox,new TGLayoutHints(kLHintsTop|kLHintsLeft, - 5, 5, 5, 5)); -``` - -We create the list box widget passing the parent window pointer and -giving an ID number. Next we add entries with specified string and ID to -the list box. Before adding the list box to its parent widget, it should -be resized via `Resize(width, height)` method. The list box width and -height are in pixels. The default entry layout hints are -`kLHintsExpandX | kLHintsTop`. If you want to add entries using -different ones, call the method: - -``` {.cpp} -TGListBox::AddEntry(TGLBEntry *lbe, TGLayoutHints *lhints); -``` - -It adds the specified **`TGLBEntry`** and **`TGLayoutHints`** to the -list box. There are several methods providing a flexible entry -manipulation: you can insert, add or remove list box items dynamically. -The list box entry IDs are used in these methods and also in event -processing routines. In our example the integer variables `fFirstEntry` -and `fLastEntry` contain the information about the first and last entry -IDs. You can add or remove a list box entry using them in the following -way: - -``` {.cpp} -// adding an entry -fLastEntry++; -sprintf(tmp, "Entry %i", fLastEntry); -fListBox->AddEntry(tmp, fLastEntry); -fListBox->MapSubwindows(); -fListBox->Layout(); -. . . -// removing an entry -if (fFirstEntry < fLastEntry) { - fListBox->RemoveEntry(fFirstEntry); - fListBox->Layout(); - fFirstEntry++; -} -``` - -A single-selection list box is used for selecting only one item in a -list. - -A multiple-selection list box permits selection of more than one item. -The selected choices should be visible - you have several choices to do -this: - -- to mark selected choices with a check mark or highlight them - -- to provide a summary list box to the right of the list box, - containing the selected choices - -- to provide a display-only text control indicating the number of - selected choices (its position should be justified upper-right above - the list box) - -- if the actions `Select All` or `Deselect All` must be quickly or - frequently performed, use command buttons - -### Combo Boxes - - -A combo box is as single-selection list box that shows only the -currently selected entry and a prompt button displayed as a downward -arrow. The prompt button provides a visual cue that a list box is -hidden. Its main advantage is consuming of quite a bit of screen space. -When the user clicks on it, a list pops up, from which a new choice can -be made. After a new item is chosen the combo box folds again showing -the new selection. - -![](pictures/0200021A.jpg) - -The combo box widget is represented by the user callable class -**`TGComboBox`**. The class **`TGComboBoxPopup`** is a service class. -The combo box constructor is very similar to the list box one. The first -parameter is a parent widget pointer again, the second - an integer -value that will be used as combo box ID. The method used for adding -entries is very similar to the list box method we used before. The -method `Select(entryID)` sets the current combo box entry. - -``` {.cpp} -char tmp[20]; -// combo box layout hints -fLcombo = new TGLayoutHints(kLHintsTop | kLHintsLeft,5,5,5,5); -// combo box widget -TGComboBox *fCombo = new TGComboBox(parent,100); -for (i = 0; i < 10; i++) { - sprintf(tmp, "Entry%i", i+1); - fCombo->AddEntry(tmp, i+1); -} -fCombo->Resize(150, 20); -// Entry3 is selected as current -fCombo->Select(2); -parent->AddFrame(fCombo, fLcombo); -``` - -You have the same flexibility to add, insert or remove entries. As with -list boxes you can retrieve the information for currently selected item -via `GetSelected` or `GetSelectedEntry` methods. The first one returns -the entry ID, the second - the current entry pointer -(**`TGLBEntry *`**). - -### Sliders - - -A slider is a scale with an indicator (slider) that you can drag to -choose a value from a predefined range. It may be oriented horizontally -or vertically. In both cases it provides an excellent indication of -where a value exists within a range of values. - -![](pictures/0200021B.jpg) - -The class **`TGHSlider`** represents the horizontal slider; -**`TGVSlider`** - the vertical one. Both inherit from the base class -**`TGSlider`** that creates the main slider parameters: the range of -values within a value can be selected; the indicator type; the tick mark -scale. Using its methods `SetRange`, `SetPosition` and `SetScale` you -can set these parameters. To retrieve the set slider value you can call -`GetPosition` method. - -Next sample code creates a horizontal slider `hslider` with a tick mark -of type `kSlider1`. Its width is 150 pixels, and its scale is placed -down (`kScaleDownRight`). The last parameter in the **`TGHSlider`** -constructor is the slider ID. It will be used for event processing. The -methods `SetRange` and `SetPosition` set the range and the current tick -mark position of the slider. - -``` {.cpp} -hslider = new TGHSlider(parent,150,kSlider1|kScaleDownRight,sID); -hslider->SetRange(0,50); -hslider->SetPosition(39); -``` - -Slider values can be set by using the mouse to drag the slider across -the scale until the desired value is reached. Another way is to click in -the slider trough instead of dragging. - -#### Double Slider - -Double slider widgets allow easy selection of a min and a max value out -of a range. They can be either horizontal or vertical oriented. There is -a choice of different types of tick marks: `kDoubleScaleNo`, -`kScaleDownRight`, `kDoubleScaleBoth`. - -To change the `min` value you should press the left mouse button near to -the left (**`TGDoubleHSlider`**) or bottom (**`TGDoubleHSlider`**) edge -of the slider. Alternatively, to change the `max` value you need to -press the mouse near to the right (**`TGDoubleHSlider`**) or top -(**`TGDoubleHSlider`**) edge of the slider. To change both values -simultaneously you should press the left mouse button near to the center -of the slider. - -![](pictures/0200021C.jpg) - -**`TGDoubleSlider`** is an abstract base class that creates the main -slider parameters. The concrete class to use for a vertical double -slider is **`TGDoubleVSlider`** and **`TGDoubleHSlider`** for a -horizontal one. The double slider constructors are similar to those of -the other sliders. If you set `kDoubleScaleNo` as a scale parameter no -scale will be drawn. Here is an example: - -``` {.cpp} -vDslider = new TGDoubleVSlider(p,100,kDoubleScaleNo,dsliderID); -vDslider->SetRange(-10,10); -``` - -### Triple Slider - - -The new **`TGTripleHSlider`** and **`TGTripleVSlider`** classes inherit -from the double slider widgets and allow easy selection of a range and a -pointer value. The pointer position can be constrained into the selected -range or can be relative to it. - -![](pictures/0300021D.png) - -To change the slider range value press the left mouse button near to the -left/right (top/bottom) edges of the slider. To change both values -simultaneously press the mouse button near to the slider center. To -change pointer value press the mouse on the pointer and drag it to the -desired position. - -``` {.cpp} -fSlider = new TGTripleHSlider(parent,100,kDoubleScaleBoth,kSLD_ID, - kHorizontalFrame); -parent->AddFrame(fSlider,new TGLayoutHints(kLHintsExpandX,5,5,5,5)); -fSlider->SetConstrained(kTRUE); -fSlider->SetRange(rmin, rmax); -fSlider->SetPosition(pmin, pmax); -fSlider ->SetPointerPosition(pvalue); -``` - -### Progress Bars - - -A progress bar is a widget that shows that an operation is in progress -and how much time is left. It is a long rectangular bar, initially -empty, that fills with a color as a process is being performed. The -filled-in area indicates the percentage of the process that has been -completed. You should use this widget for waits exceeding `one minute`. -For a very time consuming operation it is better to break the operation -into subtasks and provide a progress bar for each of them. - -![](pictures/0200021E.jpg) - -A progress bar may be oriented horizontally or vertically. The -horizontally oriented progress bar fills with a color from left to -right; the vertically oriented - from bottom to top. A percent complete -message provides an indication of the completed part of the process. It -is a good practice to include some descriptive text of the process to -keep users informed and entertained while they are waiting for process -completion. - -The picture below shows the progress bars you can create using the -classes **`TGProgressBar`**, **`TGHProgressBar`**, and -**`TGHProgressBar`**. - -``` {.cpp} -// vertical frame with three horizontal progressive bars -TGVerticalFrame *vframe = new TGVerticalFrame(fMain, 10, 10); -fHProg1 = new TGHProgressBar(vframe,TGProgressBar::kStandard,300); -fHProg1->ShowPosition(); -fHProg1->SetBarColor("yellow"); -fHProg2 = new TGHProgressBar(vframe,TGProgressBar::kFancy,300); -fHProg2->SetBarColor("lightblue"); -fHProg2->ShowPosition(kTRUE,kFALSE,"%.0f events"); -fHProg3 = new TGHProgressBar(vframe,TGProgressBar::kStandard,300); -fHProg3->SetFillType(TGProgressBar::kBlockFill); - -vframe->AddFrame(fHProg1,new TGLayoutHints(kLHintsTop|kLHintsLeft| - kLHintsExpandX,5,5,5,10)); -vframe->AddFrame(fHProg2,new TGLayoutHints(kLHintsTop|kLHintsLeft| - kLHintsExpandX,5,5,5,10)); -vframe->AddFrame(fHProg3,new TGLayoutHints(kLHintsTop|kLHintsLeft| - kLHintsExpandX,5,5,5,10)); -vframe->Resize(200, 200); -``` - -### Static Widgets - - -The classes **`TGLabel`** and **`TGIcon`** show some information - text -or graphics. The line below creates a label object. The syntax is very -simple: you specify the parent widget and a string object holding the -desired text. - -``` {.cpp} -TGLabel *label = new TGLabel(parentWidget, "Label's string"); -``` - -Next sample creates an icon object. First we create an object of type -**`TGPicture`**. The **`TGPicture`** objects are never created directly -by the application code. We call **`TGClient`** telling it the pixmap's -file name to create a **`TGPicture`** object and, in turn, it will -return a pointer to the created object. If the pixmap file cannot be -found the returned pointer will be `NULL`. As usual, the first parameter -of a **`TGIcon`** constructor is the parent frame. The second one is the -**`TGPicture`** object holding the pixmap we want to show. Last two -parameters define the width and height of pixmap in pixels. In the end -we add the created icon object to its parent. - -``` {.cpp} -// icon widget -const TGPicture *ipic=(TGPicture *)gClient->GetPicture("leaf.xpm"); -TGIcon *icon = new TGIcon(parent,ipic,40,40); -parent->AddFrame(icon,new TGLayoutHints(kLHintsLeft|kLHintsBottom, - 1, 15, 1, 1)); -``` - -The **`TGPicture`** objects are cached by **`TGClient`** in order to -keep the resource usage low and to improve the efficiency of the -client-server windowing systems. **`TGClient`** will check whether a -pixmap with the same name was already loaded before to register a new -picture object. If it finds it, it will return a pointer to the existing -object. Also, it will increase the usage counter for the object. - -All **`TGPicture`** objects are managed by the class -**`TGPicturePool`**. **`TGClient`** creates an object of this type upon -initialization. Normally your application program does not deal directly -with this class because all manipulations go through **`TGClient`** -class. - -Once you have finished with using of the **`TGPicture`** object, you -should call the method **`TGClient::FreePicture(const TGPicture *pic)`** -to free it. The usage counter of the picture object will be decreased -and when it reaches zero - the **`TGPicture`** object will be deleted. - -### Status Bar - - -The status bar widget is used to display some information about the -current application state: what is being viewed in the window, a -descriptive message about selected objects, or other no interactive -information. It may also be used to explain highlighted menu and tool -bar items. - -![](pictures/0200021F.jpg) - -An application can only have one status bar at a time. - -There is nothing special to create a status bar in your application. You -should decide how many fields you need to present the current -application state to the user. By default a status bar consists of one -part. Multiple parts can be created by `SetParts` method. Its first -parameter is an array of integers that give the percentage size of each -part. The second parameter gives the number of status bar parts. Using -`SetText` method you can set a text for any part. - -``` {.cpp} -// status bar -Int_t parts[] = {33, 10, 10, 47}; -fStatusBar = new TGStatusBar(fMain,50,10,kHorizontalFrame); -fStatusbar->SetParts(parts,4); -fMain->AddFrame(fStatusBar, new TGLayoutHints(kLHintsBottom | - kLHintsLeft | kLHintsExpandX, 0, 0, 2, 0)); -. . . -// fill status bar fields with information; selected is the object -// below the cursor; atext contains pixel coordinates info -fStatusBar->SetText(selected->GetTitle(),0); -fStatusBar->SetText(selected->GetName(),1); -fStatusBar->SetText(atext,2); -fStatusBar->SetText(selected->GetObjectInfo(px,py),3); -``` - -### Splitters - - -A window can be split into two parts (panes) by using a horizontal or a -vertical splitter. A horizontal splitter resizes the frames above and -below of it; a vertical splitter resizes the frames left and right of -it. - -![](pictures/02000220.jpg) - -This widget is represented by **`TGSplitter`**, **`TGHSplitter`**, and -**`TGVSplitter`** classes. Currently there is no special graphics -representation for splitter widgets; only the cursor changes when -crossing a splitter. - -There is nothing special to create a splitter - two lines of code only: - -``` {.cpp} -TGHSplitter *hsplitter = new TGHSplitter(fVf); -hsplitter->SetFrame(fH1,kTRUE); -``` - -You call a horizontal **`TGHSplitter`** or a vertical **`TGVSplitter`** -splitter constructor and after you set the frame to be resized via -`SetFrame` method. In spite of that, there are rules to be followed when -you create a splitter in your application. - -For a `horizontal` splitter they are: - -- the parent of a horizontal splitter must inherit from - **`TGCompoziteFrame`** and must have a vertical layout - -- the `above` resized frame must have `kFixedHeight` option set - -- use layout hints `kLHintsTop | kLHintsExpandX` when adding the - **`above`** resized frame to its parent - -- use layout hints `kLHintsBottom | kLHintsExpandX | kLHintsExpandY` - when adding the bottom resized frame to its parent - -- set the **`above`** frame to be resized using `SetFrame` method; the - second parameter should be `kTRUE` - -You can see these rules in the code below: - -``` {.cpp} -// Create horizontal splitter -fVf = new TGVerticalFrame(fMain,10,10); -fH1 = new TGHorizontalFrame(fVf,10,10, kFixedHeight); -fH2 = new TGHorizontalFrame(fVf,10,10); -fFtop = new TGCompositeFrame(fH1,10,10, kSunkenFrame); -fFbottom = new TGCompositeFrame(fH2,10,10,kSunkenFrame); -fLtop = new TGLabel(fFtop,"Top Frame"); -fLbottom = new TGLabel(fFbottom,"Bottom Frame"); - -fFtop->AddFrame(fLtop, new TGLayoutHints(kLHintsLeft | - kLHintsCenterY,3,0,0,0)); -fFbottom->AddFrame(fLbottom, new TGLayoutHints(kLHintsLeft | - kLHintsCenterY,3,0,0,0)); -fH1->AddFrame(fFtop, new TGLayoutHints(kLHintsTop | - kLHintsExpandY | kLHintsExpandX,0,0,1,2)); -fH2->AddFrame(fFbottom,new TGLayoutHints(kLHintsTop | - kLHintsExpandY | kLHintsExpandX,0,0,1,2)); -fH1->Resize(fFtop->GetDefaultWidth(),fH1->GetDefaultHeight()+20); -fH2->Resize(fFbottom->GetDefaultWidth(),fH2->GetDefaultHeight()+20); -fVf->AddFrame(fH1, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); - -TGHSplitter *hsplitter = new TGHSplitter(fVf); -hsplitter->SetFrame(fH1,kTRUE); -fVf->AddFrame(hsplitter,new TGLayoutHints(kLHintsTop | - kLHintsExpandX)); -fVf->AddFrame(fH2, new TGLayoutHints(kLHintsBottom | - kLHintsExpandX | kLHintsExpandY)); -``` - -For a `vertical` splitter the rules are: - -- the parent of a vertical splitter must inherit from - **`TGCompoziteFrame`** and must have a horizontal layout - -- the `left` resized frame must have `kFixedWidth` option set - -- use layout hints `kLHintsLeft | kLHintsExpandY` when adding the - `left` resized frame to the parent - -- use layout hints `kLHintsRight|kLHintsExpandX |kLHintsExpandY` when - adding the right resized frame to the parent - -- set the `left` frame to be resized using `SetFrame` method; the - second parameter should be `kTRUE` - -Next is a sample code for a vertical splitter: - -``` {.cpp} -// Create vertical splitter -fHf = new TGHorizontalFrame(fMain, 50, 50); -fV1 = new TGVerticalFrame(fHf, 10, 10, kFixedWidth); -fV2 = new TGVerticalFrame(fHf, 10, 10); -fFleft = new TGCompositeFrame(fV1, 10, 10, kSunkenFrame); -fFright = new TGCompositeFrame(fV2, 10, 10, kSunkenFrame); - -fLleft = new TGLabel(fFleft, "Left Frame"); -fLright = new TGLabel(fFright, "Right Frame"); - -fFleft->AddFrame(fLleft, new TGLayoutHints(kLHintsLeft | - kLHintsCenterY,3,0,0,0)); -fFright->AddFrame(fLright, new TGLayoutHints(kLHintsLeft | - kLHintsCenterY,3,0,0,0)); -fV1->AddFrame(fFleft,new TGLayoutHints(kLHintsTop | - kLHintsExpandX | kLHintsExpandY,0,0,5,5)); -fV2->AddFrame(fFright,new TGLayoutHints(kLHintsTop | - kLHintsExpandX | kLHintsExpandY, 0, 0, 5, 5)); -fV1->Resize(fFleft->GetDefaultWidth()+20, fV1->GetDefaultHeight()); -fV2->Resize(fFright->GetDefaultWidth(), fV1->GetDefaultHeight()); -fHf->AddFrame(fV1,new TGLayoutHints(kLHintsLeft | kLHintsExpandY)); - -splitter = new TGVSplitter(fHf,2,30); -splitter->SetFrame(fV1, kTRUE); -fHf->AddFrame(splitter,new TGLayoutHints(kLHintsLeft | - kLHintsExpandY)); -fHf->AddFrame(fV2,new TGLayoutHints(kLHintsRight | kLHintsExpandX | - kLHintsExpandY)); -``` - -### TGCanvas, ViewPort and Container - - -When all display information cannot be presented in a window, the -additional information must be found and made visible. A **`TGCanvas`** -is a frame containing two scrollbars (horizontal and vertical) and a -viewport (**`TGViewPort`**). The viewport acts as the window through -which we look at the contents of the container frame. A -**`TGContainer`** frame manages a content area. It can display and -control a hierarchy of multi-column items, and provides the ability to -add new items at any time. By default it doesn't map sub-windows, which -are items of the container. In this case sub-window must provide -`DrawCopy` method, see for example **`TGLVEntry`** class. It is also -possible to use option which allows mapping sub-windows. This option has -much slower drawing speed in case of more than 1000 items placed in -container. To activate this option the fMapSubwindows data member must -be set to `kTRUE` (for example **`TTVLVContainer`** class). - -A scroll bar only is available when scrolling is necessary. It consists -of three elements: a slider box and two directional scroll arrows -(buttons). - -``` {.cpp} -fCanvas = new TGCanvas(parent, w, h); -fContents = new TGListTree(fCanvas, kHorizontalFrame); -fContents->Associate(parent); -parent->AddFrame(fCanvas, new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY)); -// or -fCanvas = new TGCanvas(parent, w, h); -fContents = new TGListTree(fCanvas->GetViewPort(),100,100, - kHorizontalFrame); -fContents->SetCanvas(fCanvas); -fContents->Associate(parent); -fCanvas->SetContainer(fContents); -parent->AddFrame(fCanvas, new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY)); -``` - -The **`TGContainer`** class can handle the following keys: - -F7, Ctnrl-Factivate a search dialog - -F3, Ctnrl-Gcontinue to search - -Endgo to the last item in container - -Homego to the first item in container - -PageUpnavigate up - -PageDownnavigate down - -arrow keysnavigate inside container - -Return/Enterequivalent to double click of the mouse button - -Contrl-Aselect all items - -Spaceinvert selection. - -### Embedded Canvas - - -This class creates a **`TGCanvas`** in which a well known ROOT -**`TCanvas`** is embedded. A pointer to the **`TCanvas`** can be -obtained via the `GetCanvas()` member function. - -``` {.cpp} -fEc1 = new TRootEmbeddedCanvas("ec1",fParent,100,100); -fParent ->AddFrame(fEc1, new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY)); -fEc2 = new TRootEmbeddedCanvas("ec2",fParent,100,100); -fParent ->AddFrame(fEc2, new TGLayoutHints(kLHintsExpandX | - kLHintsExpandY)); -fEc1->GetCanvas()->SetBorderMode(0); -fEc2->GetCanvas()->SetBorderMode(0); -fEc1->GetCanvas()->SetBit(kNoContextMenu); -fEc1->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", - "MyClass", this, "HandleMyCanvas(Int_t,Int_t,Int_t,TObject*)"); -``` - -![](pictures/03000221.png) - -To embed a canvas derived from a **`TCanvas`** do the following: - -``` {.cpp} -TRootEmbeddedCanvas *embed = new TRootEmbeddedCanvas(0, p, w, h); -// note name must be 0, not null string "" -Int_t wid = embed->GetCanvasWindowId(); -TCanvas *myc = new TCanvas("myname",10,10,wid); -embed->AdoptCanvas(myc); -// the TCanvas is adopted by the embedded canvas and will be -// destroyed by it -``` - -## The ROOT Graphics Editor (GED) - - -Everything drawn in a ROOT canvas is an object. There are classes for -all objects, and they fall into hierarchies. In addition, the ROOT has -fully cross-platform GUI classes and provides all standard components -for an application environment with common ‘look and feel'. The -object-oriented, event-driven programming model supports the modern -signals/slots communication mechanism. It handles user interface actions -and allows total independence of interacting objects and classes. This -mechanism uses the ROOT dictionary information and the Cling the C++ -Interpreter to connect signals to slots methods. - -Therefore, all necessary elements for an object-oriented editor design -are in place. The editor complexity can be reduced by splitting it into -discrete units of so-called *`object`* *`editors`*. Any object editor -provides an object specific GUI. The main purpose of the ROOT graphics -editor is the organization of the object editors' appearance and the -task sequence between them. - -### Object Editors - - -Every object editor follows a simple naming convention: to have as a -name the object class name concatenated with ‘*`Editor`*' (e.g. for -**`TGraph`** objects the object editor is **`TGraphEditor`**). Thanks to -the signals/slots communication mechanism and to the method -`DistancetoPrimitive()` that computes a ‘‘distance'' to an object from -the mouse position, it was possible to implement a signal method of the -canvas that says which is the selected object and to which pad it -belongs. Having this information the graphics editor loads the -corresponding object editor and the user interface is ready for use. -This way after a click on ‘axis'—the axis editor is active; a click on a -‘pad' activates the pad editor, etc. - -The algorithm in use is simple and is based on the object-oriented -relationship and communication. When the user activates the editor, -according to the selected object **``** in the canvas it looks for -a class name **`Editor`**. For that reason, the correct naming is -very important. If a class with this name is found, the editor verifies -that this class derives from the base editor class **`TGedFrame`**. If -all checks are satisfied, the editor makes an instance of the object -editor. Then, it scans all object base classes searching the -corresponding object editors. When it finds one, it makes an instance of -the base class editor too. - -Once the object editor is in place, it sets the user interface elements -according to the object's status. After that, it is ready to interact -with the object following the user actions. - -The graphics editor gives an intuitive way to edit objects in a canvas -with immediate feedback. Complexity of some object editors is reduced by -hiding GUI elements and revealing them only on users' requests. - -An object in the canvas is selected by clicking on it with the left -mouse button. Its name is displayed on the top of the editor frame in -red color. If the editor frame needs more space than the canvas window, -a vertical scroll bar appears for easy navigation. - -![Histogram, pad and axis editors](pictures/03000222.png) - -### Editor Design Elements - - -The next rules describe the path to follow when creating your own object -editor that will be recognized and loaded by the graphics editor in -ROOT, i.e. it will be included as a part of it. - -(a) Derive the code of your object editor from the base editor class -**`TGedFrame`**. - -(b) Keep the correct naming convention: the name of the object editor -should be the object class name concatenated with the word `‘Editor'`. - -(c) Provide a default constructor. - -(d) Use the signals/slots communication mechanism for event processing. - -(e) Implement the virtual method `SetModel(TObject *obj)` where all -widgets are set with the current object's attributes. This method is -called when the editor receives a signal from the canvas saying that an -object is the selected. - -(f) Implement all necessary slots and connect them to appropriate -signals that GUI widgets send out. The GUI classes in ROOT are developed -to emit signals whenever they change a state that others might be -interested. As we noted already, the signals/slots communication -mechanism allows total independence of the interacting classes. - -#### Creation and Destruction - -GED-frames are constructed during traversal of class hierarchy of the -selected object, executed from method **`TGedEditor`**`::SetModel()`. -When a new object of a different class is selected, the unneeded -GED-frames are cached in memory for potential reuse. The frames are -deleted automatically when the editor is closed. - -Note: A deep cleanup is assumed for all frames put into the editor. This -implies: - -- do not share the layout-hints among GUI components; - -- do not delete child widgets in the destructor as this is done - automatically. - -#### Using Several Tabs - -Sometimes you might need to use several tabs to organize properly your -class-editor. Each editor tab is a resource shared among all the -class-editors. Tabs must be created from the constructor of your -editor-class by using the method: - -``` {.cpp} -TGVerticalFrame* TGedFrame::CreateEditorTabSubFrame(const Text_t *name), -``` - -It returns a pointer to a new tab container frame ready for use in your -class. If you need to hide/show this frame depending on the object's -status, you should store it in a data member. See for examples: -**`TH1Editor`**, **`TH2Editor`**. - -#### Base-Class Editors Control - -Full control over base-class editors can be achieved by re-implementing -virtual method void `TGedFrame::ActivateBaseClassEditors(TClass` `*cl)`. -It is called during each compound editor rebuild and the default -implementation simply offers all base-classes to the publishing -mechanism. - -To prevent inclusion of a base-class into the compound editor, call: - -``` {.cpp} -void TGedEditor::ExcludeClassEditor(TClass* class, Bool_t recurse) -``` - -Pointer to the compound GED-editor is available in **`TGedFrame`**‘s -data-member: - -``` {.cpp} -TGedEditor *fGedEditor -``` - -Ordering of base-class editor frames follows the order of the classes in -the class hierarchy. This order can be changed by modifying the value of -**`TGedFrame`**'s data member `Int_t fPriority`. The default value is -50; smaller values move the frame towards to the top. This priority -should be set in the editor constructor. - -## Drag and Drop - - -Drag and Drop support is introduced for Linux (via Xdnd - the drag and -drop protocol for X window system) and for Windows (via Clipboard). -Users can selects something in ROOT with a mouse press, drags it (moves -the mouse while keeping the mouse button pressed) and releases the mouse -button someplace else. When the button is released the selected data is -"dropped" at that location. This way, a histogram from an opened ROOT -file in the browser can be dragged to any **`TCanvas`**. - -![](pictures/03000223.png) - -A script file from the browser can be dropped to a **`TGTextView`** or -TGTextEdit widget in **`TGTextEditor`**. - -On Linux, it is possible to drag objects between ROOT and an external -application. For example to drag a macro file from the ROOT browser to -the Kate editor. On Windows, drag and drop works only within a single -ROOT application (for the time being), but works also from Windows -Explorer to **`TCanvas`** ot to **`TGTextEdit`**. - -### Drag and Drop Data Class - - -The Drag and Drop Cata class **`TDNDdata`** is used to describe and -handle the transferred data during an drag and drop operation. It -consists of: - -`Atom_t fDataType`: atom describing the data type. - -`Atom_t fAction`: atom describing the action (copy, move, link); -currently, only copy is used. - -`void *fData`: actual data (buffer). - -`Int_t` `fDataLength`: length (size) of data buffer. - -Currently two types are recognized by ROOT: "application/root" for ROOT -objects and "text/uri-list" for path/filenames (uri comes from Unique -Resource Identifier). A text/uri-list is a standard file listing format -for drag and drop that specifies a list of files (each file per line). -Each line ends with a carriage return and newline` rn`. File names have -to be valid, url-encoded URI's as shown below: - -`file://localhost/usr/bin/opera` or -`file://localhost/c:/programs/myfile.txt` - -`file://server/data/software.xml` or -`http://root.cern.ch/root/images/ftpstats.gif` - -The atoms and the drag and drop manager (**`TGDNDManager`**), are -created at the main application creation time (class TGMainFrame). - -Setting a Drag Source - first, create and fill data: - -``` {.cpp} -TH1F *h = new TH1F("h","h",1000,-3,3); -h->FillRandom("gaus",50000); -TDNDdata data; -TBufferFile *buf = new TBufferFile(TBuffer::kWrite); -buf->WriteObject(h); -data.fData = buf->Buffer(); -data.fDataLength = buf->Length(); -data.fDataType = gVirtualX->InternAtom("application/root"); -``` - -Then, set a GUI widget as DND Source, and associate the data. Source -widget can be any class inheriting from **`TGFrame`**. - -``` {.cpp} -SourceWidget=new TGIcon(this,gClient->GetPicture("f1_s.xpm"),32,32); -SourceWidget->SetDNDSource(kTRUE); -SourceWidget->SetDNDdata(&data); -``` - -Setting A Drop Target - set the widget as DND Target, and set the DND -types it must be aware of: as `SourceWidget`, `TargetWidget` can be any -class inheriting from **`TGFrame`**. - -``` {.cpp} -TargetWidget = new TRootEmbeddedCanvas("Target", this, 700, 400); -TargetWidget->SetDNDTarget(kTRUE); -gVirtualX->SetDNDAware(TargetWidget->GetId(), - gDNDManager->GetTypeList()); -``` - -`gDNDManager->GetTypeList()` returns the list of types recognized by -ROOT. - -Note that the Widget may receive drag and drop messages with drop-data -it does not understand, and thus it should only accept drops of the -proper type. - -### Handling Drag and Drop Events - - -Once a widget has been set as DND Target, it has to handle Drag and Drop -events. - -`Atom_t HandleDNDenter(Atom_t *typelist)` - this method is used to -handle a drag operation entering the widget. The typelist parameter is -the list of types the data contains. If the list contains one type the -widget understands, it should return this type to notify the manager -that the drop would be accepted, i.e. : - -``` {.cpp} -for (int i = 0; typelist[i] != kNone; ++i) { - if (typelist[i] == gVirtualX->InternAtom("application/root")) - // accept "application/root" DND type - return typelist[i]; -} -// other type not accepted -return kNone; -``` - -`Atom_t HandleDNDposition(Int_t x,Int_t y,Atom_t action,Int_t xroot, -Int_t yroot)` - this -method should be used to handle the drag position in widget coordinates -(`x,y`) or in root coordinates (`xroot,yroot`). - -``` {.cpp} -// get the pad over which the cursor is -TPad *pad = fCanvas->Pick(x, y, 0); -if (pad) { - pad->cd(); - gROOT->SetSelectedPad(pad); -} -return action; -``` - -`Bool_t HandleDNDdrop(TDNDdata *data)` - this is the place where the -widget actually receives the data. First, check the data format (see -description of **`TDNDData`** - Drag and Drop data class) and then use -it accordingly. In the case of ROOT object, here is an example of how to -retrieve it: - -``` {.cpp} -if (data->fDataType == gVirtualX->InternAtom("application/root")) { - TBufferFile buf(TBuffer::kRead, data->fDataLength, - (void *)data->fData); - buf.SetReadMode(); - TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class()); - if (obj->IsA()->GetMethodAllAny("Draw")) - obj->Draw(); -} -``` - -In the case of URI/list, the use is: - -``` {.cpp} -if (data->fDataType == gVirtualX->InternAtom("text/uri-list")) { - TString sfname((char *)data->fData); - TUrl uri(sfname.Data()); - if (sfname.EndsWith(".jpg") - TImage *img = TImage::Open(uri.GetFile()); -} -``` - -`Bool_t HandleDNDleave()` is used if a specific action has to be -performed when the drag operation leaves the widget. diff --git a/documentation/users-guide/css/github.css b/documentation/users-guide/css/github.css deleted file mode 100644 index 43c250265ce8c..0000000000000 --- a/documentation/users-guide/css/github.css +++ /dev/null @@ -1,308 +0,0 @@ - diff --git a/documentation/users-guide/metadata.xml b/documentation/users-guide/metadata.xml deleted file mode 100644 index 5b1f91cdfb0e2..0000000000000 --- a/documentation/users-guide/metadata.xml +++ /dev/null @@ -1,2 +0,0 @@ -Creative Commons Non-Commercial Share Alike 3.0 -en-US diff --git a/documentation/users-guide/pictures/02000004.jpg b/documentation/users-guide/pictures/02000004.jpg deleted file mode 100644 index 20a6fb4625c73..0000000000000 Binary files a/documentation/users-guide/pictures/02000004.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000030.png b/documentation/users-guide/pictures/02000030.png deleted file mode 100644 index 3395b13cf2bc3..0000000000000 Binary files a/documentation/users-guide/pictures/02000030.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000031.png b/documentation/users-guide/pictures/02000031.png deleted file mode 100644 index 99c94a45d37f0..0000000000000 Binary files a/documentation/users-guide/pictures/02000031.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000032.png b/documentation/users-guide/pictures/02000032.png deleted file mode 100644 index ab83dee3b6f04..0000000000000 Binary files a/documentation/users-guide/pictures/02000032.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000034.png b/documentation/users-guide/pictures/02000034.png deleted file mode 100644 index be43f6d77c954..0000000000000 Binary files a/documentation/users-guide/pictures/02000034.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000035.png b/documentation/users-guide/pictures/02000035.png deleted file mode 100644 index 5773d6e3c43a2..0000000000000 Binary files a/documentation/users-guide/pictures/02000035.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000036.png b/documentation/users-guide/pictures/02000036.png deleted file mode 100644 index 9a7074ad975a3..0000000000000 Binary files a/documentation/users-guide/pictures/02000036.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000037.png b/documentation/users-guide/pictures/02000037.png deleted file mode 100644 index 0a86ec2acadea..0000000000000 Binary files a/documentation/users-guide/pictures/02000037.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000039.png b/documentation/users-guide/pictures/02000039.png deleted file mode 100644 index 7a9e3d1705d98..0000000000000 Binary files a/documentation/users-guide/pictures/02000039.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0200003C.png b/documentation/users-guide/pictures/0200003C.png deleted file mode 100644 index 47f0b1e8757e9..0000000000000 Binary files a/documentation/users-guide/pictures/0200003C.png and /dev/null differ diff --git a/documentation/users-guide/pictures/02000095.jpg b/documentation/users-guide/pictures/02000095.jpg deleted file mode 100644 index 94488f5df13af..0000000000000 Binary files a/documentation/users-guide/pictures/02000095.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000096.jpg b/documentation/users-guide/pictures/02000096.jpg deleted file mode 100644 index f06e6cd3d381c..0000000000000 Binary files a/documentation/users-guide/pictures/02000096.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000097.jpg b/documentation/users-guide/pictures/02000097.jpg deleted file mode 100644 index 05deff8a55aab..0000000000000 Binary files a/documentation/users-guide/pictures/02000097.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000098.jpg b/documentation/users-guide/pictures/02000098.jpg deleted file mode 100644 index 127649a808c91..0000000000000 Binary files a/documentation/users-guide/pictures/02000098.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000099.jpg b/documentation/users-guide/pictures/02000099.jpg deleted file mode 100644 index b9a28608200e8..0000000000000 Binary files a/documentation/users-guide/pictures/02000099.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200009A.jpg b/documentation/users-guide/pictures/0200009A.jpg deleted file mode 100644 index e48c31cb27995..0000000000000 Binary files a/documentation/users-guide/pictures/0200009A.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200009B.jpg b/documentation/users-guide/pictures/0200009B.jpg deleted file mode 100644 index bc3ee118d1666..0000000000000 Binary files a/documentation/users-guide/pictures/0200009B.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200009C.jpg b/documentation/users-guide/pictures/0200009C.jpg deleted file mode 100644 index 2454c58a55a5c..0000000000000 Binary files a/documentation/users-guide/pictures/0200009C.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200009D.jpg b/documentation/users-guide/pictures/0200009D.jpg deleted file mode 100644 index ef79672599e1a..0000000000000 Binary files a/documentation/users-guide/pictures/0200009D.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200009E.jpg b/documentation/users-guide/pictures/0200009E.jpg deleted file mode 100644 index 35d954091b4cf..0000000000000 Binary files a/documentation/users-guide/pictures/0200009E.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000A4.jpg b/documentation/users-guide/pictures/020000A4.jpg deleted file mode 100644 index c2b0f04226843..0000000000000 Binary files a/documentation/users-guide/pictures/020000A4.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000A6.jpg b/documentation/users-guide/pictures/020000A6.jpg deleted file mode 100644 index 08537382dc637..0000000000000 Binary files a/documentation/users-guide/pictures/020000A6.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000A7.jpg b/documentation/users-guide/pictures/020000A7.jpg deleted file mode 100644 index 5ae08f2e7c03e..0000000000000 Binary files a/documentation/users-guide/pictures/020000A7.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000A8.jpg b/documentation/users-guide/pictures/020000A8.jpg deleted file mode 100644 index 1cc4fcf8f12c7..0000000000000 Binary files a/documentation/users-guide/pictures/020000A8.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000A9.jpg b/documentation/users-guide/pictures/020000A9.jpg deleted file mode 100644 index 6fb00bebbd9dc..0000000000000 Binary files a/documentation/users-guide/pictures/020000A9.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000AA.jpg b/documentation/users-guide/pictures/020000AA.jpg deleted file mode 100644 index 1c7d022b8ef43..0000000000000 Binary files a/documentation/users-guide/pictures/020000AA.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000AB.jpg b/documentation/users-guide/pictures/020000AB.jpg deleted file mode 100644 index 8ee90cad5fa15..0000000000000 Binary files a/documentation/users-guide/pictures/020000AB.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000AC.jpg b/documentation/users-guide/pictures/020000AC.jpg deleted file mode 100644 index 391111b5aa715..0000000000000 Binary files a/documentation/users-guide/pictures/020000AC.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000AF.jpg b/documentation/users-guide/pictures/020000AF.jpg deleted file mode 100644 index 7b04b7a907a7b..0000000000000 Binary files a/documentation/users-guide/pictures/020000AF.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000C1.jpg b/documentation/users-guide/pictures/020000C1.jpg deleted file mode 100644 index 371ada4cb064c..0000000000000 Binary files a/documentation/users-guide/pictures/020000C1.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000C2.jpg b/documentation/users-guide/pictures/020000C2.jpg deleted file mode 100644 index 11b014265499c..0000000000000 Binary files a/documentation/users-guide/pictures/020000C2.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000C3.jpg b/documentation/users-guide/pictures/020000C3.jpg deleted file mode 100644 index 83ddf53afa48b..0000000000000 Binary files a/documentation/users-guide/pictures/020000C3.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000DA.jpg b/documentation/users-guide/pictures/020000DA.jpg deleted file mode 100644 index 1415ac51e87f5..0000000000000 Binary files a/documentation/users-guide/pictures/020000DA.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000DB.jpg b/documentation/users-guide/pictures/020000DB.jpg deleted file mode 100644 index e287edcc06c0b..0000000000000 Binary files a/documentation/users-guide/pictures/020000DB.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000DC.jpg b/documentation/users-guide/pictures/020000DC.jpg deleted file mode 100644 index 05306500ecf00..0000000000000 Binary files a/documentation/users-guide/pictures/020000DC.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000DD.jpg b/documentation/users-guide/pictures/020000DD.jpg deleted file mode 100644 index 227537f885c02..0000000000000 Binary files a/documentation/users-guide/pictures/020000DD.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000E2.jpg b/documentation/users-guide/pictures/020000E2.jpg deleted file mode 100644 index 679b88fed52f4..0000000000000 Binary files a/documentation/users-guide/pictures/020000E2.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000E3.jpg b/documentation/users-guide/pictures/020000E3.jpg deleted file mode 100644 index 9e83234f2076b..0000000000000 Binary files a/documentation/users-guide/pictures/020000E3.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000EB.jpg b/documentation/users-guide/pictures/020000EB.jpg deleted file mode 100644 index 936d3cc59bbca..0000000000000 Binary files a/documentation/users-guide/pictures/020000EB.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000EC.jpg b/documentation/users-guide/pictures/020000EC.jpg deleted file mode 100644 index e60147b9f3725..0000000000000 Binary files a/documentation/users-guide/pictures/020000EC.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000ED.jpg b/documentation/users-guide/pictures/020000ED.jpg deleted file mode 100644 index 619f1e78264bf..0000000000000 Binary files a/documentation/users-guide/pictures/020000ED.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000EE.jpg b/documentation/users-guide/pictures/020000EE.jpg deleted file mode 100644 index 421624bfa98c7..0000000000000 Binary files a/documentation/users-guide/pictures/020000EE.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020000F1.jpg b/documentation/users-guide/pictures/020000F1.jpg deleted file mode 100644 index 91dbcac1957cc..0000000000000 Binary files a/documentation/users-guide/pictures/020000F1.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000101.jpg b/documentation/users-guide/pictures/02000101.jpg deleted file mode 100644 index bda150e9ba48c..0000000000000 Binary files a/documentation/users-guide/pictures/02000101.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000102.jpg b/documentation/users-guide/pictures/02000102.jpg deleted file mode 100644 index b65250126de48..0000000000000 Binary files a/documentation/users-guide/pictures/02000102.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000108.jpg b/documentation/users-guide/pictures/02000108.jpg deleted file mode 100644 index f3fafc720898b..0000000000000 Binary files a/documentation/users-guide/pictures/02000108.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000109.jpg b/documentation/users-guide/pictures/02000109.jpg deleted file mode 100644 index 9bb16cbbd6bc7..0000000000000 Binary files a/documentation/users-guide/pictures/02000109.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001A3.jpg b/documentation/users-guide/pictures/020001A3.jpg deleted file mode 100644 index d56be173798dd..0000000000000 Binary files a/documentation/users-guide/pictures/020001A3.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001A4.jpg b/documentation/users-guide/pictures/020001A4.jpg deleted file mode 100644 index 4957f4cb34fea..0000000000000 Binary files a/documentation/users-guide/pictures/020001A4.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001A5.jpg b/documentation/users-guide/pictures/020001A5.jpg deleted file mode 100644 index f34d6327773a7..0000000000000 Binary files a/documentation/users-guide/pictures/020001A5.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001A6.jpg b/documentation/users-guide/pictures/020001A6.jpg deleted file mode 100644 index 23f605fb1655e..0000000000000 Binary files a/documentation/users-guide/pictures/020001A6.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001A7.jpg b/documentation/users-guide/pictures/020001A7.jpg deleted file mode 100644 index 3c1f36f8a09b1..0000000000000 Binary files a/documentation/users-guide/pictures/020001A7.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001A8.jpg b/documentation/users-guide/pictures/020001A8.jpg deleted file mode 100644 index 7f1d1600f2c5e..0000000000000 Binary files a/documentation/users-guide/pictures/020001A8.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001B1.jpg b/documentation/users-guide/pictures/020001B1.jpg deleted file mode 100644 index 74ec511d3e2a3..0000000000000 Binary files a/documentation/users-guide/pictures/020001B1.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001B2.jpg b/documentation/users-guide/pictures/020001B2.jpg deleted file mode 100644 index 444627e8bc3d9..0000000000000 Binary files a/documentation/users-guide/pictures/020001B2.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001E4.jpg b/documentation/users-guide/pictures/020001E4.jpg deleted file mode 100644 index bca84d5af59e0..0000000000000 Binary files a/documentation/users-guide/pictures/020001E4.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001EA.jpg b/documentation/users-guide/pictures/020001EA.jpg deleted file mode 100644 index 598751e94f2e1..0000000000000 Binary files a/documentation/users-guide/pictures/020001EA.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001EB.jpg b/documentation/users-guide/pictures/020001EB.jpg deleted file mode 100644 index 9ce2d5e6aa1ea..0000000000000 Binary files a/documentation/users-guide/pictures/020001EB.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001EC.jpg b/documentation/users-guide/pictures/020001EC.jpg deleted file mode 100644 index 225de0e531622..0000000000000 Binary files a/documentation/users-guide/pictures/020001EC.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001ED.jpg b/documentation/users-guide/pictures/020001ED.jpg deleted file mode 100644 index 4c74bdc8dd5ea..0000000000000 Binary files a/documentation/users-guide/pictures/020001ED.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001EE.jpg b/documentation/users-guide/pictures/020001EE.jpg deleted file mode 100644 index 0dd8174acecf9..0000000000000 Binary files a/documentation/users-guide/pictures/020001EE.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F0.jpg b/documentation/users-guide/pictures/020001F0.jpg deleted file mode 100644 index 17e65407e2034..0000000000000 Binary files a/documentation/users-guide/pictures/020001F0.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F1.jpg b/documentation/users-guide/pictures/020001F1.jpg deleted file mode 100644 index bbcfce81786a5..0000000000000 Binary files a/documentation/users-guide/pictures/020001F1.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F2.jpg b/documentation/users-guide/pictures/020001F2.jpg deleted file mode 100644 index 779533d3fd462..0000000000000 Binary files a/documentation/users-guide/pictures/020001F2.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F3.jpg b/documentation/users-guide/pictures/020001F3.jpg deleted file mode 100644 index 0ab168f715281..0000000000000 Binary files a/documentation/users-guide/pictures/020001F3.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F5.jpg b/documentation/users-guide/pictures/020001F5.jpg deleted file mode 100644 index be328e470dea4..0000000000000 Binary files a/documentation/users-guide/pictures/020001F5.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F6.jpg b/documentation/users-guide/pictures/020001F6.jpg deleted file mode 100644 index 5d9f857ce6b3b..0000000000000 Binary files a/documentation/users-guide/pictures/020001F6.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F7.jpg b/documentation/users-guide/pictures/020001F7.jpg deleted file mode 100644 index 6a7373d7e3e8c..0000000000000 Binary files a/documentation/users-guide/pictures/020001F7.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/020001F8.jpg b/documentation/users-guide/pictures/020001F8.jpg deleted file mode 100644 index 0c9896c8ddfdd..0000000000000 Binary files a/documentation/users-guide/pictures/020001F8.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000201.jpg b/documentation/users-guide/pictures/02000201.jpg deleted file mode 100644 index 1d29d90da73d1..0000000000000 Binary files a/documentation/users-guide/pictures/02000201.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000202.jpg b/documentation/users-guide/pictures/02000202.jpg deleted file mode 100644 index 537354bea1afd..0000000000000 Binary files a/documentation/users-guide/pictures/02000202.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000203.jpg b/documentation/users-guide/pictures/02000203.jpg deleted file mode 100644 index b789939ef0c6a..0000000000000 Binary files a/documentation/users-guide/pictures/02000203.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000204.jpg b/documentation/users-guide/pictures/02000204.jpg deleted file mode 100644 index a953c10587d78..0000000000000 Binary files a/documentation/users-guide/pictures/02000204.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000205.jpg b/documentation/users-guide/pictures/02000205.jpg deleted file mode 100644 index 4f506e08ce542..0000000000000 Binary files a/documentation/users-guide/pictures/02000205.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000206.jpg b/documentation/users-guide/pictures/02000206.jpg deleted file mode 100644 index 63de133e0b716..0000000000000 Binary files a/documentation/users-guide/pictures/02000206.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000207.jpg b/documentation/users-guide/pictures/02000207.jpg deleted file mode 100644 index ad01b8e462439..0000000000000 Binary files a/documentation/users-guide/pictures/02000207.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000208.jpg b/documentation/users-guide/pictures/02000208.jpg deleted file mode 100644 index a11b5f2dbecef..0000000000000 Binary files a/documentation/users-guide/pictures/02000208.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000209.jpg b/documentation/users-guide/pictures/02000209.jpg deleted file mode 100644 index 5c84909ecea40..0000000000000 Binary files a/documentation/users-guide/pictures/02000209.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200020A.jpg b/documentation/users-guide/pictures/0200020A.jpg deleted file mode 100644 index e836a69698e7e..0000000000000 Binary files a/documentation/users-guide/pictures/0200020A.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200020B.jpg b/documentation/users-guide/pictures/0200020B.jpg deleted file mode 100644 index 9be97245c90ac..0000000000000 Binary files a/documentation/users-guide/pictures/0200020B.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200020C.jpg b/documentation/users-guide/pictures/0200020C.jpg deleted file mode 100644 index ae1610f3a7322..0000000000000 Binary files a/documentation/users-guide/pictures/0200020C.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200020E.jpg b/documentation/users-guide/pictures/0200020E.jpg deleted file mode 100644 index ace414a2e1d1a..0000000000000 Binary files a/documentation/users-guide/pictures/0200020E.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200020F.jpg b/documentation/users-guide/pictures/0200020F.jpg deleted file mode 100644 index a72c3442dc4e3..0000000000000 Binary files a/documentation/users-guide/pictures/0200020F.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000219.jpg b/documentation/users-guide/pictures/02000219.jpg deleted file mode 100644 index 61ee6cfad905f..0000000000000 Binary files a/documentation/users-guide/pictures/02000219.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200021A.jpg b/documentation/users-guide/pictures/0200021A.jpg deleted file mode 100644 index f0303713b5a4b..0000000000000 Binary files a/documentation/users-guide/pictures/0200021A.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200021B.jpg b/documentation/users-guide/pictures/0200021B.jpg deleted file mode 100644 index d6c060eb6e82c..0000000000000 Binary files a/documentation/users-guide/pictures/0200021B.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200021C.jpg b/documentation/users-guide/pictures/0200021C.jpg deleted file mode 100644 index b63d53573b315..0000000000000 Binary files a/documentation/users-guide/pictures/0200021C.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200021E.jpg b/documentation/users-guide/pictures/0200021E.jpg deleted file mode 100644 index 7861a111e8526..0000000000000 Binary files a/documentation/users-guide/pictures/0200021E.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200021F.jpg b/documentation/users-guide/pictures/0200021F.jpg deleted file mode 100644 index f87b822a46800..0000000000000 Binary files a/documentation/users-guide/pictures/0200021F.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000220.jpg b/documentation/users-guide/pictures/02000220.jpg deleted file mode 100644 index fc2e41654317e..0000000000000 Binary files a/documentation/users-guide/pictures/02000220.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000228.jpg b/documentation/users-guide/pictures/02000228.jpg deleted file mode 100644 index 5cc28bea3b281..0000000000000 Binary files a/documentation/users-guide/pictures/02000228.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/02000229.jpg b/documentation/users-guide/pictures/02000229.jpg deleted file mode 100644 index 83363911300ef..0000000000000 Binary files a/documentation/users-guide/pictures/02000229.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200022A.jpg b/documentation/users-guide/pictures/0200022A.jpg deleted file mode 100644 index fd494d5f18811..0000000000000 Binary files a/documentation/users-guide/pictures/0200022A.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/0200022C.jpg b/documentation/users-guide/pictures/0200022C.jpg deleted file mode 100644 index 27c422ac98b8e..0000000000000 Binary files a/documentation/users-guide/pictures/0200022C.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/03000005.png b/documentation/users-guide/pictures/03000005.png deleted file mode 100644 index 0ac2b28e21e54..0000000000000 Binary files a/documentation/users-guide/pictures/03000005.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000006.png b/documentation/users-guide/pictures/03000006.png deleted file mode 100644 index ac23fa1af3318..0000000000000 Binary files a/documentation/users-guide/pictures/03000006.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000007.png b/documentation/users-guide/pictures/03000007.png deleted file mode 100644 index 5eeec86a84dfe..0000000000000 Binary files a/documentation/users-guide/pictures/03000007.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000008.png b/documentation/users-guide/pictures/03000008.png deleted file mode 100644 index a617766a9f2eb..0000000000000 Binary files a/documentation/users-guide/pictures/03000008.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000009.png b/documentation/users-guide/pictures/03000009.png deleted file mode 100644 index a88ad3fbfc22d..0000000000000 Binary files a/documentation/users-guide/pictures/03000009.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300000A.png b/documentation/users-guide/pictures/0300000A.png deleted file mode 100644 index 45b6151738732..0000000000000 Binary files a/documentation/users-guide/pictures/0300000A.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300000B.png b/documentation/users-guide/pictures/0300000B.png deleted file mode 100644 index b5873845e234e..0000000000000 Binary files a/documentation/users-guide/pictures/0300000B.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300000C.png b/documentation/users-guide/pictures/0300000C.png deleted file mode 100644 index f882198902215..0000000000000 Binary files a/documentation/users-guide/pictures/0300000C.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300000D.png b/documentation/users-guide/pictures/0300000D.png deleted file mode 100644 index c08e1c87c4e1e..0000000000000 Binary files a/documentation/users-guide/pictures/0300000D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300000E.png b/documentation/users-guide/pictures/0300000E.png deleted file mode 100644 index 68a8b78f5422c..0000000000000 Binary files a/documentation/users-guide/pictures/0300000E.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300000F.png b/documentation/users-guide/pictures/0300000F.png deleted file mode 100644 index e9553042b659a..0000000000000 Binary files a/documentation/users-guide/pictures/0300000F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000010.png b/documentation/users-guide/pictures/03000010.png deleted file mode 100644 index 3d5ad878d8f84..0000000000000 Binary files a/documentation/users-guide/pictures/03000010.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000011.png b/documentation/users-guide/pictures/03000011.png deleted file mode 100644 index 15de17e7fa42b..0000000000000 Binary files a/documentation/users-guide/pictures/03000011.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000012.png b/documentation/users-guide/pictures/03000012.png deleted file mode 100644 index a60164bf3a74f..0000000000000 Binary files a/documentation/users-guide/pictures/03000012.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000013.png b/documentation/users-guide/pictures/03000013.png deleted file mode 100644 index 4ea63df7ed630..0000000000000 Binary files a/documentation/users-guide/pictures/03000013.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000014.png b/documentation/users-guide/pictures/03000014.png deleted file mode 100644 index 2a003fd8eaed3..0000000000000 Binary files a/documentation/users-guide/pictures/03000014.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000015.png b/documentation/users-guide/pictures/03000015.png deleted file mode 100644 index 3ba8c8f99b98b..0000000000000 Binary files a/documentation/users-guide/pictures/03000015.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000016.png b/documentation/users-guide/pictures/03000016.png deleted file mode 100644 index 5ef2595858570..0000000000000 Binary files a/documentation/users-guide/pictures/03000016.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000017.png b/documentation/users-guide/pictures/03000017.png deleted file mode 100644 index 61fab1f033190..0000000000000 Binary files a/documentation/users-guide/pictures/03000017.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000018.png b/documentation/users-guide/pictures/03000018.png deleted file mode 100644 index f2165b9d771a2..0000000000000 Binary files a/documentation/users-guide/pictures/03000018.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000019.png b/documentation/users-guide/pictures/03000019.png deleted file mode 100644 index 53b1cc0d563b6..0000000000000 Binary files a/documentation/users-guide/pictures/03000019.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300001A.png b/documentation/users-guide/pictures/0300001A.png deleted file mode 100644 index 41667498eed41..0000000000000 Binary files a/documentation/users-guide/pictures/0300001A.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300001B.png b/documentation/users-guide/pictures/0300001B.png deleted file mode 100644 index 9de3f5a4315be..0000000000000 Binary files a/documentation/users-guide/pictures/0300001B.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300001C.png b/documentation/users-guide/pictures/0300001C.png deleted file mode 100644 index e7c1dd1ff8537..0000000000000 Binary files a/documentation/users-guide/pictures/0300001C.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300001D.png b/documentation/users-guide/pictures/0300001D.png deleted file mode 100644 index cd416b8aaceab..0000000000000 Binary files a/documentation/users-guide/pictures/0300001D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300001E.png b/documentation/users-guide/pictures/0300001E.png deleted file mode 100644 index 02c2f499e1e7b..0000000000000 Binary files a/documentation/users-guide/pictures/0300001E.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300001F.png b/documentation/users-guide/pictures/0300001F.png deleted file mode 100644 index 3da0b99e51f4d..0000000000000 Binary files a/documentation/users-guide/pictures/0300001F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000020.png b/documentation/users-guide/pictures/03000020.png deleted file mode 100644 index 008fc1765917d..0000000000000 Binary files a/documentation/users-guide/pictures/03000020.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000021.png b/documentation/users-guide/pictures/03000021.png deleted file mode 100644 index 45031eed15bf2..0000000000000 Binary files a/documentation/users-guide/pictures/03000021.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000022.png b/documentation/users-guide/pictures/03000022.png deleted file mode 100644 index 21fa2821ae476..0000000000000 Binary files a/documentation/users-guide/pictures/03000022.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000023.png b/documentation/users-guide/pictures/03000023.png deleted file mode 100644 index 3e1a5c6343929..0000000000000 Binary files a/documentation/users-guide/pictures/03000023.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000024.png b/documentation/users-guide/pictures/03000024.png deleted file mode 100644 index 1dffa5160108a..0000000000000 Binary files a/documentation/users-guide/pictures/03000024.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000025.png b/documentation/users-guide/pictures/03000025.png deleted file mode 100644 index 161cd550b4de9..0000000000000 Binary files a/documentation/users-guide/pictures/03000025.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000026.png b/documentation/users-guide/pictures/03000026.png deleted file mode 100644 index 4ff123c630a6d..0000000000000 Binary files a/documentation/users-guide/pictures/03000026.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000027.png b/documentation/users-guide/pictures/03000027.png deleted file mode 100644 index c926364285ec7..0000000000000 Binary files a/documentation/users-guide/pictures/03000027.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000028.png b/documentation/users-guide/pictures/03000028.png deleted file mode 100644 index d07071d2fb31b..0000000000000 Binary files a/documentation/users-guide/pictures/03000028.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300002A.png b/documentation/users-guide/pictures/0300002A.png deleted file mode 100644 index 15a8bc5625ca9..0000000000000 Binary files a/documentation/users-guide/pictures/0300002A.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300002B.png b/documentation/users-guide/pictures/0300002B.png deleted file mode 100644 index e36cc3893c5d0..0000000000000 Binary files a/documentation/users-guide/pictures/0300002B.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300002D.png b/documentation/users-guide/pictures/0300002D.png deleted file mode 100644 index 0eab1d42953cc..0000000000000 Binary files a/documentation/users-guide/pictures/0300002D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300002F.png b/documentation/users-guide/pictures/0300002F.png deleted file mode 100644 index dbe4282fa204b..0000000000000 Binary files a/documentation/users-guide/pictures/0300002F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000033.png b/documentation/users-guide/pictures/03000033.png deleted file mode 100644 index 7090a51883eb7..0000000000000 Binary files a/documentation/users-guide/pictures/03000033.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000038.png b/documentation/users-guide/pictures/03000038.png deleted file mode 100644 index 8efc6ce413f48..0000000000000 Binary files a/documentation/users-guide/pictures/03000038.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300003A.png b/documentation/users-guide/pictures/0300003A.png deleted file mode 100644 index ebea4e4eeb9bd..0000000000000 Binary files a/documentation/users-guide/pictures/0300003A.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300003D.png b/documentation/users-guide/pictures/0300003D.png deleted file mode 100644 index 9adafc876a5e2..0000000000000 Binary files a/documentation/users-guide/pictures/0300003D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300003E.png b/documentation/users-guide/pictures/0300003E.png deleted file mode 100644 index b1758e1943c3b..0000000000000 Binary files a/documentation/users-guide/pictures/0300003E.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000040.png b/documentation/users-guide/pictures/03000040.png deleted file mode 100644 index 4e92d51bb4969..0000000000000 Binary files a/documentation/users-guide/pictures/03000040.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000041.png b/documentation/users-guide/pictures/03000041.png deleted file mode 100644 index 539db0567b6ef..0000000000000 Binary files a/documentation/users-guide/pictures/03000041.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000042.png b/documentation/users-guide/pictures/03000042.png deleted file mode 100644 index 199c202735ed2..0000000000000 Binary files a/documentation/users-guide/pictures/03000042.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000043.png b/documentation/users-guide/pictures/03000043.png deleted file mode 100644 index 90a6fce32b17b..0000000000000 Binary files a/documentation/users-guide/pictures/03000043.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000045.png b/documentation/users-guide/pictures/03000045.png deleted file mode 100644 index 9eb1e09e3b4f8..0000000000000 Binary files a/documentation/users-guide/pictures/03000045.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000047.png b/documentation/users-guide/pictures/03000047.png deleted file mode 100644 index 2a5d39d1654a8..0000000000000 Binary files a/documentation/users-guide/pictures/03000047.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000049.png b/documentation/users-guide/pictures/03000049.png deleted file mode 100644 index cf06e5fceca74..0000000000000 Binary files a/documentation/users-guide/pictures/03000049.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300004B.png b/documentation/users-guide/pictures/0300004B.png deleted file mode 100644 index e2184085456d5..0000000000000 Binary files a/documentation/users-guide/pictures/0300004B.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300004C.png b/documentation/users-guide/pictures/0300004C.png deleted file mode 100644 index 2935f1f81950a..0000000000000 Binary files a/documentation/users-guide/pictures/0300004C.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300004D.png b/documentation/users-guide/pictures/0300004D.png deleted file mode 100644 index 26b20781506db..0000000000000 Binary files a/documentation/users-guide/pictures/0300004D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300004E.png b/documentation/users-guide/pictures/0300004E.png deleted file mode 100644 index 183b905ccbfa5..0000000000000 Binary files a/documentation/users-guide/pictures/0300004E.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300004F.png b/documentation/users-guide/pictures/0300004F.png deleted file mode 100644 index aea1342fa229d..0000000000000 Binary files a/documentation/users-guide/pictures/0300004F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000050.png b/documentation/users-guide/pictures/03000050.png deleted file mode 100644 index d071918bb8329..0000000000000 Binary files a/documentation/users-guide/pictures/03000050.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000052.png b/documentation/users-guide/pictures/03000052.png deleted file mode 100644 index 1f4ec452d2ede..0000000000000 Binary files a/documentation/users-guide/pictures/03000052.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000053.png b/documentation/users-guide/pictures/03000053.png deleted file mode 100644 index 768150cc98f41..0000000000000 Binary files a/documentation/users-guide/pictures/03000053.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000054.png b/documentation/users-guide/pictures/03000054.png deleted file mode 100644 index 2e0e97be6e250..0000000000000 Binary files a/documentation/users-guide/pictures/03000054.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000055.png b/documentation/users-guide/pictures/03000055.png deleted file mode 100644 index 5c79778b59192..0000000000000 Binary files a/documentation/users-guide/pictures/03000055.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000056.png b/documentation/users-guide/pictures/03000056.png deleted file mode 100644 index dc0cca11280f6..0000000000000 Binary files a/documentation/users-guide/pictures/03000056.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000057.png b/documentation/users-guide/pictures/03000057.png deleted file mode 100644 index 001e7c51ea919..0000000000000 Binary files a/documentation/users-guide/pictures/03000057.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000058.png b/documentation/users-guide/pictures/03000058.png deleted file mode 100644 index 34328d3f113cd..0000000000000 Binary files a/documentation/users-guide/pictures/03000058.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000059.png b/documentation/users-guide/pictures/03000059.png deleted file mode 100644 index 57b9c1ca48429..0000000000000 Binary files a/documentation/users-guide/pictures/03000059.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300005A.png b/documentation/users-guide/pictures/0300005A.png deleted file mode 100644 index 79a4e9bd8835b..0000000000000 Binary files a/documentation/users-guide/pictures/0300005A.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300005C.png b/documentation/users-guide/pictures/0300005C.png deleted file mode 100644 index 1c15bdaa2f094..0000000000000 Binary files a/documentation/users-guide/pictures/0300005C.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300005D.png b/documentation/users-guide/pictures/0300005D.png deleted file mode 100644 index a3c61566103b8..0000000000000 Binary files a/documentation/users-guide/pictures/0300005D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300005E.png b/documentation/users-guide/pictures/0300005E.png deleted file mode 100644 index 9a131fb7976fc..0000000000000 Binary files a/documentation/users-guide/pictures/0300005E.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300005F.png b/documentation/users-guide/pictures/0300005F.png deleted file mode 100644 index 0bd3d53a5713d..0000000000000 Binary files a/documentation/users-guide/pictures/0300005F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000060.png b/documentation/users-guide/pictures/03000060.png deleted file mode 100644 index a6082c263a8dc..0000000000000 Binary files a/documentation/users-guide/pictures/03000060.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000061.png b/documentation/users-guide/pictures/03000061.png deleted file mode 100644 index b2f12af731518..0000000000000 Binary files a/documentation/users-guide/pictures/03000061.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000062.png b/documentation/users-guide/pictures/03000062.png deleted file mode 100644 index 10634508d496b..0000000000000 Binary files a/documentation/users-guide/pictures/03000062.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000070.png b/documentation/users-guide/pictures/03000070.png deleted file mode 100644 index 0be5c5fd6555d..0000000000000 Binary files a/documentation/users-guide/pictures/03000070.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300008D.png b/documentation/users-guide/pictures/0300008D.png deleted file mode 100644 index 2332ac1559aa3..0000000000000 Binary files a/documentation/users-guide/pictures/0300008D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000092.png b/documentation/users-guide/pictures/03000092.png deleted file mode 100644 index fcb2d19b4806b..0000000000000 Binary files a/documentation/users-guide/pictures/03000092.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000093.png b/documentation/users-guide/pictures/03000093.png deleted file mode 100644 index 0dcb42a753643..0000000000000 Binary files a/documentation/users-guide/pictures/03000093.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000094.png b/documentation/users-guide/pictures/03000094.png deleted file mode 100644 index 527931131b582..0000000000000 Binary files a/documentation/users-guide/pictures/03000094.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300009F.png b/documentation/users-guide/pictures/0300009F.png deleted file mode 100644 index 43233445099ef..0000000000000 Binary files a/documentation/users-guide/pictures/0300009F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000A0.png b/documentation/users-guide/pictures/030000A0.png deleted file mode 100644 index 4c3d16ca46456..0000000000000 Binary files a/documentation/users-guide/pictures/030000A0.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000A5.png b/documentation/users-guide/pictures/030000A5.png deleted file mode 100644 index 04e23c049c1c2..0000000000000 Binary files a/documentation/users-guide/pictures/030000A5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000AD.png b/documentation/users-guide/pictures/030000AD.png deleted file mode 100644 index bced86558dffb..0000000000000 Binary files a/documentation/users-guide/pictures/030000AD.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000AE.png b/documentation/users-guide/pictures/030000AE.png deleted file mode 100644 index 9d9d74e9e7e96..0000000000000 Binary files a/documentation/users-guide/pictures/030000AE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000B0.png b/documentation/users-guide/pictures/030000B0.png deleted file mode 100644 index 680d0ab9dc806..0000000000000 Binary files a/documentation/users-guide/pictures/030000B0.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000B1.png b/documentation/users-guide/pictures/030000B1.png deleted file mode 100644 index 60967950e186d..0000000000000 Binary files a/documentation/users-guide/pictures/030000B1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000B2.png b/documentation/users-guide/pictures/030000B2.png deleted file mode 100644 index be9fc9e8b9848..0000000000000 Binary files a/documentation/users-guide/pictures/030000B2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000B3.png b/documentation/users-guide/pictures/030000B3.png deleted file mode 100644 index d6d42cc51eb38..0000000000000 Binary files a/documentation/users-guide/pictures/030000B3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000B4.png b/documentation/users-guide/pictures/030000B4.png deleted file mode 100644 index 2a8d2535cb398..0000000000000 Binary files a/documentation/users-guide/pictures/030000B4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000BC.png b/documentation/users-guide/pictures/030000BC.png deleted file mode 100644 index 7d9e7ae665bae..0000000000000 Binary files a/documentation/users-guide/pictures/030000BC.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000BD.png b/documentation/users-guide/pictures/030000BD.png deleted file mode 100644 index 0fd3ba3c94cdf..0000000000000 Binary files a/documentation/users-guide/pictures/030000BD.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000BE.png b/documentation/users-guide/pictures/030000BE.png deleted file mode 100644 index 2c90a1f61489c..0000000000000 Binary files a/documentation/users-guide/pictures/030000BE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000C5.png b/documentation/users-guide/pictures/030000C5.png deleted file mode 100644 index 3e56efcc8730c..0000000000000 Binary files a/documentation/users-guide/pictures/030000C5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000C6.png b/documentation/users-guide/pictures/030000C6.png deleted file mode 100644 index e3994952eee45..0000000000000 Binary files a/documentation/users-guide/pictures/030000C6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000C7.png b/documentation/users-guide/pictures/030000C7.png deleted file mode 100644 index b5a1f2c2537c6..0000000000000 Binary files a/documentation/users-guide/pictures/030000C7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000C8.png b/documentation/users-guide/pictures/030000C8.png deleted file mode 100644 index 24ecc1019dd44..0000000000000 Binary files a/documentation/users-guide/pictures/030000C8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000C9.png b/documentation/users-guide/pictures/030000C9.png deleted file mode 100644 index 9e87c494bedf5..0000000000000 Binary files a/documentation/users-guide/pictures/030000C9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000CA.png b/documentation/users-guide/pictures/030000CA.png deleted file mode 100644 index a3ad5165ab21e..0000000000000 Binary files a/documentation/users-guide/pictures/030000CA.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000CB.png b/documentation/users-guide/pictures/030000CB.png deleted file mode 100644 index 8a883e4ebcdb3..0000000000000 Binary files a/documentation/users-guide/pictures/030000CB.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000CC.png b/documentation/users-guide/pictures/030000CC.png deleted file mode 100644 index 482fe367ea3da..0000000000000 Binary files a/documentation/users-guide/pictures/030000CC.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000CD.png b/documentation/users-guide/pictures/030000CD.png deleted file mode 100644 index aadfec67f4487..0000000000000 Binary files a/documentation/users-guide/pictures/030000CD.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000CE.png b/documentation/users-guide/pictures/030000CE.png deleted file mode 100644 index d6fa6f25b0e68..0000000000000 Binary files a/documentation/users-guide/pictures/030000CE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000CF.png b/documentation/users-guide/pictures/030000CF.png deleted file mode 100644 index 35858cde3b93e..0000000000000 Binary files a/documentation/users-guide/pictures/030000CF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D0.png b/documentation/users-guide/pictures/030000D0.png deleted file mode 100644 index 861cb3b3f9b76..0000000000000 Binary files a/documentation/users-guide/pictures/030000D0.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D1.png b/documentation/users-guide/pictures/030000D1.png deleted file mode 100644 index 88a6d24b11ec7..0000000000000 Binary files a/documentation/users-guide/pictures/030000D1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D2.png b/documentation/users-guide/pictures/030000D2.png deleted file mode 100644 index 90934305fac7f..0000000000000 Binary files a/documentation/users-guide/pictures/030000D2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D3.png b/documentation/users-guide/pictures/030000D3.png deleted file mode 100644 index 7c1298fe2467a..0000000000000 Binary files a/documentation/users-guide/pictures/030000D3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D4.png b/documentation/users-guide/pictures/030000D4.png deleted file mode 100644 index 4310b2ca5c308..0000000000000 Binary files a/documentation/users-guide/pictures/030000D4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D5.png b/documentation/users-guide/pictures/030000D5.png deleted file mode 100644 index d01e9c0e3faf5..0000000000000 Binary files a/documentation/users-guide/pictures/030000D5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D6.png b/documentation/users-guide/pictures/030000D6.png deleted file mode 100644 index 80a073f45fb67..0000000000000 Binary files a/documentation/users-guide/pictures/030000D6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D7.png b/documentation/users-guide/pictures/030000D7.png deleted file mode 100644 index 94d5510b68d5b..0000000000000 Binary files a/documentation/users-guide/pictures/030000D7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D8.png b/documentation/users-guide/pictures/030000D8.png deleted file mode 100644 index f255b76616149..0000000000000 Binary files a/documentation/users-guide/pictures/030000D8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000D9.png b/documentation/users-guide/pictures/030000D9.png deleted file mode 100644 index 0dde229d66c76..0000000000000 Binary files a/documentation/users-guide/pictures/030000D9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000DE.png b/documentation/users-guide/pictures/030000DE.png deleted file mode 100644 index 77dbbf9eace23..0000000000000 Binary files a/documentation/users-guide/pictures/030000DE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000DF.png b/documentation/users-guide/pictures/030000DF.png deleted file mode 100644 index 75f0830ee1d61..0000000000000 Binary files a/documentation/users-guide/pictures/030000DF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E0.png b/documentation/users-guide/pictures/030000E0.png deleted file mode 100644 index 0f3a0e184d5f9..0000000000000 Binary files a/documentation/users-guide/pictures/030000E0.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E1.png b/documentation/users-guide/pictures/030000E1.png deleted file mode 100644 index 1bd4972a89a2c..0000000000000 Binary files a/documentation/users-guide/pictures/030000E1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E4.png b/documentation/users-guide/pictures/030000E4.png deleted file mode 100644 index 221d385ddf00a..0000000000000 Binary files a/documentation/users-guide/pictures/030000E4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E5.png b/documentation/users-guide/pictures/030000E5.png deleted file mode 100644 index 078e9df848c73..0000000000000 Binary files a/documentation/users-guide/pictures/030000E5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E6.png b/documentation/users-guide/pictures/030000E6.png deleted file mode 100644 index 0f74d098af2e3..0000000000000 Binary files a/documentation/users-guide/pictures/030000E6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E7.png b/documentation/users-guide/pictures/030000E7.png deleted file mode 100644 index 70dcfdfd422b3..0000000000000 Binary files a/documentation/users-guide/pictures/030000E7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E8.png b/documentation/users-guide/pictures/030000E8.png deleted file mode 100644 index 922380e3c54d5..0000000000000 Binary files a/documentation/users-guide/pictures/030000E8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000E9.png b/documentation/users-guide/pictures/030000E9.png deleted file mode 100644 index ea076f26005e8..0000000000000 Binary files a/documentation/users-guide/pictures/030000E9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000EA.png b/documentation/users-guide/pictures/030000EA.png deleted file mode 100644 index 03bfa57737ce6..0000000000000 Binary files a/documentation/users-guide/pictures/030000EA.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000EF.png b/documentation/users-guide/pictures/030000EF.png deleted file mode 100644 index 7180a3bfc41b2..0000000000000 Binary files a/documentation/users-guide/pictures/030000EF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000F2.png b/documentation/users-guide/pictures/030000F2.png deleted file mode 100644 index 9e2f7afc2a3c7..0000000000000 Binary files a/documentation/users-guide/pictures/030000F2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000F3.png b/documentation/users-guide/pictures/030000F3.png deleted file mode 100644 index 023f5660cffa0..0000000000000 Binary files a/documentation/users-guide/pictures/030000F3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000F4.png b/documentation/users-guide/pictures/030000F4.png deleted file mode 100644 index 2fee3ccdaaf58..0000000000000 Binary files a/documentation/users-guide/pictures/030000F4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000F5.png b/documentation/users-guide/pictures/030000F5.png deleted file mode 100644 index da66e52f9dc7d..0000000000000 Binary files a/documentation/users-guide/pictures/030000F5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000F6.png b/documentation/users-guide/pictures/030000F6.png deleted file mode 100644 index 576dca1db9e1b..0000000000000 Binary files a/documentation/users-guide/pictures/030000F6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000F8.png b/documentation/users-guide/pictures/030000F8.png deleted file mode 100644 index 72af283ed3b53..0000000000000 Binary files a/documentation/users-guide/pictures/030000F8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000FA.png b/documentation/users-guide/pictures/030000FA.png deleted file mode 100644 index 193325a4951fb..0000000000000 Binary files a/documentation/users-guide/pictures/030000FA.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000FC.png b/documentation/users-guide/pictures/030000FC.png deleted file mode 100644 index 670d3fdb6fef7..0000000000000 Binary files a/documentation/users-guide/pictures/030000FC.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000FE.png b/documentation/users-guide/pictures/030000FE.png deleted file mode 100644 index a8f6543a64ac9..0000000000000 Binary files a/documentation/users-guide/pictures/030000FE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030000FF.png b/documentation/users-guide/pictures/030000FF.png deleted file mode 100644 index 0db29e2f71803..0000000000000 Binary files a/documentation/users-guide/pictures/030000FF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000103.png b/documentation/users-guide/pictures/03000103.png deleted file mode 100644 index 8bdda8ab45aaa..0000000000000 Binary files a/documentation/users-guide/pictures/03000103.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000104.png b/documentation/users-guide/pictures/03000104.png deleted file mode 100644 index 550ccec9cc44d..0000000000000 Binary files a/documentation/users-guide/pictures/03000104.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000105.png b/documentation/users-guide/pictures/03000105.png deleted file mode 100644 index 91c8035c1400a..0000000000000 Binary files a/documentation/users-guide/pictures/03000105.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000106.png b/documentation/users-guide/pictures/03000106.png deleted file mode 100644 index c0be6546b6598..0000000000000 Binary files a/documentation/users-guide/pictures/03000106.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000128.png b/documentation/users-guide/pictures/03000128.png deleted file mode 100644 index de42be2bf62f4..0000000000000 Binary files a/documentation/users-guide/pictures/03000128.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300012D.png b/documentation/users-guide/pictures/0300012D.png deleted file mode 100644 index 20b55c1633a88..0000000000000 Binary files a/documentation/users-guide/pictures/0300012D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001A1.png b/documentation/users-guide/pictures/030001A1.png deleted file mode 100644 index 5343afb82f350..0000000000000 Binary files a/documentation/users-guide/pictures/030001A1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001A9.png b/documentation/users-guide/pictures/030001A9.png deleted file mode 100644 index b030dd28f54f6..0000000000000 Binary files a/documentation/users-guide/pictures/030001A9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001B3.png b/documentation/users-guide/pictures/030001B3.png deleted file mode 100644 index 6395d6b741b11..0000000000000 Binary files a/documentation/users-guide/pictures/030001B3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001B4.png b/documentation/users-guide/pictures/030001B4.png deleted file mode 100644 index 18c149a660255..0000000000000 Binary files a/documentation/users-guide/pictures/030001B4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001B5.png b/documentation/users-guide/pictures/030001B5.png deleted file mode 100644 index b12684e04d2c1..0000000000000 Binary files a/documentation/users-guide/pictures/030001B5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001C9.png b/documentation/users-guide/pictures/030001C9.png deleted file mode 100644 index 9fe1b837d3c82..0000000000000 Binary files a/documentation/users-guide/pictures/030001C9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001CE.png b/documentation/users-guide/pictures/030001CE.png deleted file mode 100644 index 9e5fbad43f346..0000000000000 Binary files a/documentation/users-guide/pictures/030001CE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001DE.png b/documentation/users-guide/pictures/030001DE.png deleted file mode 100644 index f5bfb8b7caa44..0000000000000 Binary files a/documentation/users-guide/pictures/030001DE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001DF.png b/documentation/users-guide/pictures/030001DF.png deleted file mode 100644 index 6ba3f306ae150..0000000000000 Binary files a/documentation/users-guide/pictures/030001DF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001E0.png b/documentation/users-guide/pictures/030001E0.png deleted file mode 100644 index d0ec128218a27..0000000000000 Binary files a/documentation/users-guide/pictures/030001E0.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001E1.png b/documentation/users-guide/pictures/030001E1.png deleted file mode 100644 index 1941333e8949b..0000000000000 Binary files a/documentation/users-guide/pictures/030001E1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001E2.png b/documentation/users-guide/pictures/030001E2.png deleted file mode 100644 index 64e2ff73ff6f0..0000000000000 Binary files a/documentation/users-guide/pictures/030001E2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001E3.png b/documentation/users-guide/pictures/030001E3.png deleted file mode 100644 index f857a9f4d9cc7..0000000000000 Binary files a/documentation/users-guide/pictures/030001E3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001E5.png b/documentation/users-guide/pictures/030001E5.png deleted file mode 100644 index b977c394a870d..0000000000000 Binary files a/documentation/users-guide/pictures/030001E5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001E9.png b/documentation/users-guide/pictures/030001E9.png deleted file mode 100644 index 11b361bd7412e..0000000000000 Binary files a/documentation/users-guide/pictures/030001E9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001EF.png b/documentation/users-guide/pictures/030001EF.png deleted file mode 100644 index a9a36a8d83009..0000000000000 Binary files a/documentation/users-guide/pictures/030001EF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001F4.png b/documentation/users-guide/pictures/030001F4.png deleted file mode 100644 index a7ab50df85438..0000000000000 Binary files a/documentation/users-guide/pictures/030001F4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001F9.png b/documentation/users-guide/pictures/030001F9.png deleted file mode 100644 index df14945163e95..0000000000000 Binary files a/documentation/users-guide/pictures/030001F9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001FC.png b/documentation/users-guide/pictures/030001FC.png deleted file mode 100644 index f1650fa62a29f..0000000000000 Binary files a/documentation/users-guide/pictures/030001FC.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001FD.png b/documentation/users-guide/pictures/030001FD.png deleted file mode 100644 index 5930e7ff6ef5b..0000000000000 Binary files a/documentation/users-guide/pictures/030001FD.png and /dev/null differ diff --git a/documentation/users-guide/pictures/030001FE.png b/documentation/users-guide/pictures/030001FE.png deleted file mode 100644 index 927c7f0c79b8e..0000000000000 Binary files a/documentation/users-guide/pictures/030001FE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000200.png b/documentation/users-guide/pictures/03000200.png deleted file mode 100644 index f376a0bdfcc0d..0000000000000 Binary files a/documentation/users-guide/pictures/03000200.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300020D.png b/documentation/users-guide/pictures/0300020D.png deleted file mode 100644 index b7d862938c81b..0000000000000 Binary files a/documentation/users-guide/pictures/0300020D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000210.png b/documentation/users-guide/pictures/03000210.png deleted file mode 100644 index dfdb65fccc7f0..0000000000000 Binary files a/documentation/users-guide/pictures/03000210.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000211.png b/documentation/users-guide/pictures/03000211.png deleted file mode 100644 index bd898cd0af345..0000000000000 Binary files a/documentation/users-guide/pictures/03000211.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000212.png b/documentation/users-guide/pictures/03000212.png deleted file mode 100644 index 60406fb5af1a2..0000000000000 Binary files a/documentation/users-guide/pictures/03000212.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000213.png b/documentation/users-guide/pictures/03000213.png deleted file mode 100644 index a6398bf99eb68..0000000000000 Binary files a/documentation/users-guide/pictures/03000213.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000214.png b/documentation/users-guide/pictures/03000214.png deleted file mode 100644 index 5d3fa46a9a57c..0000000000000 Binary files a/documentation/users-guide/pictures/03000214.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000215.png b/documentation/users-guide/pictures/03000215.png deleted file mode 100644 index 2d4c5b40013af..0000000000000 Binary files a/documentation/users-guide/pictures/03000215.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000216.png b/documentation/users-guide/pictures/03000216.png deleted file mode 100644 index ba55a2f346651..0000000000000 Binary files a/documentation/users-guide/pictures/03000216.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000217.png b/documentation/users-guide/pictures/03000217.png deleted file mode 100644 index d6016dd614db9..0000000000000 Binary files a/documentation/users-guide/pictures/03000217.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000218.png b/documentation/users-guide/pictures/03000218.png deleted file mode 100644 index 5f10fb7996e90..0000000000000 Binary files a/documentation/users-guide/pictures/03000218.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300021D.png b/documentation/users-guide/pictures/0300021D.png deleted file mode 100644 index 3022fb295b31b..0000000000000 Binary files a/documentation/users-guide/pictures/0300021D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000221.png b/documentation/users-guide/pictures/03000221.png deleted file mode 100644 index fbaca79b1884d..0000000000000 Binary files a/documentation/users-guide/pictures/03000221.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000222.png b/documentation/users-guide/pictures/03000222.png deleted file mode 100644 index c17cda5f7d5b6..0000000000000 Binary files a/documentation/users-guide/pictures/03000222.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000223.png b/documentation/users-guide/pictures/03000223.png deleted file mode 100644 index 56886c1e67fa7..0000000000000 Binary files a/documentation/users-guide/pictures/03000223.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000224.png b/documentation/users-guide/pictures/03000224.png deleted file mode 100644 index 430326f62cb7f..0000000000000 Binary files a/documentation/users-guide/pictures/03000224.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000225.png b/documentation/users-guide/pictures/03000225.png deleted file mode 100644 index d4fb86b9a6113..0000000000000 Binary files a/documentation/users-guide/pictures/03000225.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000226.png b/documentation/users-guide/pictures/03000226.png deleted file mode 100644 index e3e69e4297d56..0000000000000 Binary files a/documentation/users-guide/pictures/03000226.png and /dev/null differ diff --git a/documentation/users-guide/pictures/03000227.png b/documentation/users-guide/pictures/03000227.png deleted file mode 100644 index 1862833966d92..0000000000000 Binary files a/documentation/users-guide/pictures/03000227.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300022B.png b/documentation/users-guide/pictures/0300022B.png deleted file mode 100644 index b64902ed567dc..0000000000000 Binary files a/documentation/users-guide/pictures/0300022B.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0300022D.png b/documentation/users-guide/pictures/0300022D.png deleted file mode 100644 index 0848291b52fa0..0000000000000 Binary files a/documentation/users-guide/pictures/0300022D.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0600002E.png b/documentation/users-guide/pictures/0600002E.png deleted file mode 100644 index fa5370eb98475..0000000000000 Binary files a/documentation/users-guide/pictures/0600002E.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0600003B.png b/documentation/users-guide/pictures/0600003B.png deleted file mode 100644 index 1cabe352b899b..0000000000000 Binary files a/documentation/users-guide/pictures/0600003B.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060000C4.png b/documentation/users-guide/pictures/060000C4.png deleted file mode 100644 index 88a25f7ff993a..0000000000000 Binary files a/documentation/users-guide/pictures/060000C4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001B6.png b/documentation/users-guide/pictures/060001B6.png deleted file mode 100644 index 59f9dd9e501e4..0000000000000 Binary files a/documentation/users-guide/pictures/060001B6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001B7.png b/documentation/users-guide/pictures/060001B7.png deleted file mode 100644 index 4e364a5cf2d96..0000000000000 Binary files a/documentation/users-guide/pictures/060001B7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001B8.png b/documentation/users-guide/pictures/060001B8.png deleted file mode 100644 index d054e88bc3ed7..0000000000000 Binary files a/documentation/users-guide/pictures/060001B8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001B9.png b/documentation/users-guide/pictures/060001B9.png deleted file mode 100644 index 9fdb73f159a71..0000000000000 Binary files a/documentation/users-guide/pictures/060001B9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001BB.png b/documentation/users-guide/pictures/060001BB.png deleted file mode 100644 index da508bcdce4fe..0000000000000 Binary files a/documentation/users-guide/pictures/060001BB.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001BD.png b/documentation/users-guide/pictures/060001BD.png deleted file mode 100644 index 468a4fb813b4f..0000000000000 Binary files a/documentation/users-guide/pictures/060001BD.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001BE.png b/documentation/users-guide/pictures/060001BE.png deleted file mode 100644 index f3c72289e1f2d..0000000000000 Binary files a/documentation/users-guide/pictures/060001BE.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001BF.png b/documentation/users-guide/pictures/060001BF.png deleted file mode 100644 index d528dc2d27c6a..0000000000000 Binary files a/documentation/users-guide/pictures/060001BF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C0.png b/documentation/users-guide/pictures/060001C0.png deleted file mode 100644 index 0de3f7345f7fe..0000000000000 Binary files a/documentation/users-guide/pictures/060001C0.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C2.png b/documentation/users-guide/pictures/060001C2.png deleted file mode 100644 index d0f26b9d8f860..0000000000000 Binary files a/documentation/users-guide/pictures/060001C2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C3.png b/documentation/users-guide/pictures/060001C3.png deleted file mode 100644 index 5751902d9fa8d..0000000000000 Binary files a/documentation/users-guide/pictures/060001C3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C4.png b/documentation/users-guide/pictures/060001C4.png deleted file mode 100644 index f8237a79b7faa..0000000000000 Binary files a/documentation/users-guide/pictures/060001C4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C5.png b/documentation/users-guide/pictures/060001C5.png deleted file mode 100644 index 758a407ecef10..0000000000000 Binary files a/documentation/users-guide/pictures/060001C5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C7.png b/documentation/users-guide/pictures/060001C7.png deleted file mode 100644 index 0aa11b2b501b3..0000000000000 Binary files a/documentation/users-guide/pictures/060001C7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/060001C8.png b/documentation/users-guide/pictures/060001C8.png deleted file mode 100644 index c0754c4c05ade..0000000000000 Binary files a/documentation/users-guide/pictures/060001C8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/0800003F.png b/documentation/users-guide/pictures/0800003F.png deleted file mode 100644 index af5f57dbc4540..0000000000000 Binary files a/documentation/users-guide/pictures/0800003F.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080000A3.png b/documentation/users-guide/pictures/080000A3.png deleted file mode 100644 index 8ce209005d8ef..0000000000000 Binary files a/documentation/users-guide/pictures/080000A3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001BC.png b/documentation/users-guide/pictures/080001BC.png deleted file mode 100644 index 0c11c520f3bb9..0000000000000 Binary files a/documentation/users-guide/pictures/080001BC.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001C1.png b/documentation/users-guide/pictures/080001C1.png deleted file mode 100644 index a69324e6f08f5..0000000000000 Binary files a/documentation/users-guide/pictures/080001C1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001C6.png b/documentation/users-guide/pictures/080001C6.png deleted file mode 100644 index 0b8e704f771c2..0000000000000 Binary files a/documentation/users-guide/pictures/080001C6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001CA.png b/documentation/users-guide/pictures/080001CA.png deleted file mode 100644 index a77148ec5637e..0000000000000 Binary files a/documentation/users-guide/pictures/080001CA.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001CB.png b/documentation/users-guide/pictures/080001CB.png deleted file mode 100644 index 93e7c4df192d2..0000000000000 Binary files a/documentation/users-guide/pictures/080001CB.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001CC.png b/documentation/users-guide/pictures/080001CC.png deleted file mode 100644 index bf103b4325567..0000000000000 Binary files a/documentation/users-guide/pictures/080001CC.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001CD.png b/documentation/users-guide/pictures/080001CD.png deleted file mode 100644 index 706231752d83f..0000000000000 Binary files a/documentation/users-guide/pictures/080001CD.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001CF.png b/documentation/users-guide/pictures/080001CF.png deleted file mode 100644 index 22fcd4d6d319a..0000000000000 Binary files a/documentation/users-guide/pictures/080001CF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001E6.png b/documentation/users-guide/pictures/080001E6.png deleted file mode 100644 index b0a77ecba3b3c..0000000000000 Binary files a/documentation/users-guide/pictures/080001E6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001E7.png b/documentation/users-guide/pictures/080001E7.png deleted file mode 100644 index 8fee1502e46e3..0000000000000 Binary files a/documentation/users-guide/pictures/080001E7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001E8.png b/documentation/users-guide/pictures/080001E8.png deleted file mode 100644 index f9dd0277c90be..0000000000000 Binary files a/documentation/users-guide/pictures/080001E8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001FA.png b/documentation/users-guide/pictures/080001FA.png deleted file mode 100644 index d0ab17880e449..0000000000000 Binary files a/documentation/users-guide/pictures/080001FA.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001FB.png b/documentation/users-guide/pictures/080001FB.png deleted file mode 100644 index 53c310ba4bc9d..0000000000000 Binary files a/documentation/users-guide/pictures/080001FB.png and /dev/null differ diff --git a/documentation/users-guide/pictures/080001FF.png b/documentation/users-guide/pictures/080001FF.png deleted file mode 100644 index e26ec4545729a..0000000000000 Binary files a/documentation/users-guide/pictures/080001FF.png and /dev/null differ diff --git a/documentation/users-guide/pictures/Integration.png b/documentation/users-guide/pictures/Integration.png deleted file mode 100644 index 4cb019a1cc4a4..0000000000000 Binary files a/documentation/users-guide/pictures/Integration.png and /dev/null differ diff --git a/documentation/users-guide/pictures/Minimization.png b/documentation/users-guide/pictures/Minimization.png deleted file mode 100644 index d3b4a0ac37b20..0000000000000 Binary files a/documentation/users-guide/pictures/Minimization.png and /dev/null differ diff --git a/documentation/users-guide/pictures/bp1.png b/documentation/users-guide/pictures/bp1.png deleted file mode 100644 index 81a1960c70952..0000000000000 Binary files a/documentation/users-guide/pictures/bp1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/function-hierarchy.png b/documentation/users-guide/pictures/function-hierarchy.png deleted file mode 100644 index f1a8c5f482c6b..0000000000000 Binary files a/documentation/users-guide/pictures/function-hierarchy.png and /dev/null differ diff --git a/documentation/users-guide/pictures/image144.png b/documentation/users-guide/pictures/image144.png deleted file mode 100644 index 0bdb2758f4076..0000000000000 Binary files a/documentation/users-guide/pictures/image144.png and /dev/null differ diff --git a/documentation/users-guide/pictures/image145.jpg b/documentation/users-guide/pictures/image145.jpg deleted file mode 100644 index 2e545aa7debc8..0000000000000 Binary files a/documentation/users-guide/pictures/image145.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/image212.jpg b/documentation/users-guide/pictures/image212.jpg deleted file mode 100644 index a8ebac1d3152d..0000000000000 Binary files a/documentation/users-guide/pictures/image212.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/image443.jpg b/documentation/users-guide/pictures/image443.jpg deleted file mode 100644 index 082c2fd2531f3..0000000000000 Binary files a/documentation/users-guide/pictures/image443.jpg and /dev/null differ diff --git a/documentation/users-guide/pictures/mathtext.png b/documentation/users-guide/pictures/mathtext.png deleted file mode 100644 index e3c51239a01ac..0000000000000 Binary files a/documentation/users-guide/pictures/mathtext.png and /dev/null differ diff --git a/documentation/users-guide/pictures/pad_01.png b/documentation/users-guide/pictures/pad_01.png deleted file mode 100644 index 89868eccf82a6..0000000000000 Binary files a/documentation/users-guide/pictures/pad_01.png and /dev/null differ diff --git a/documentation/users-guide/pictures/pad_02.png b/documentation/users-guide/pictures/pad_02.png deleted file mode 100644 index a5d2802c1a5ed..0000000000000 Binary files a/documentation/users-guide/pictures/pad_02.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para1.png b/documentation/users-guide/pictures/para1.png deleted file mode 100644 index b83e4ffd6cab9..0000000000000 Binary files a/documentation/users-guide/pictures/para1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para10.png b/documentation/users-guide/pictures/para10.png deleted file mode 100644 index c1c3e040619f1..0000000000000 Binary files a/documentation/users-guide/pictures/para10.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para11.png b/documentation/users-guide/pictures/para11.png deleted file mode 100644 index 0bd7280532037..0000000000000 Binary files a/documentation/users-guide/pictures/para11.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para12.png b/documentation/users-guide/pictures/para12.png deleted file mode 100644 index 7d63eded4f382..0000000000000 Binary files a/documentation/users-guide/pictures/para12.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para13.png b/documentation/users-guide/pictures/para13.png deleted file mode 100644 index 678660ef1eeae..0000000000000 Binary files a/documentation/users-guide/pictures/para13.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para14.png b/documentation/users-guide/pictures/para14.png deleted file mode 100644 index 311d5bd7c6bce..0000000000000 Binary files a/documentation/users-guide/pictures/para14.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para2.png b/documentation/users-guide/pictures/para2.png deleted file mode 100644 index f8eb1290d8d2d..0000000000000 Binary files a/documentation/users-guide/pictures/para2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para3.png b/documentation/users-guide/pictures/para3.png deleted file mode 100644 index 7e6b71db65ab3..0000000000000 Binary files a/documentation/users-guide/pictures/para3.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para4.png b/documentation/users-guide/pictures/para4.png deleted file mode 100644 index 63cd29f2bf7ed..0000000000000 Binary files a/documentation/users-guide/pictures/para4.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para5.png b/documentation/users-guide/pictures/para5.png deleted file mode 100644 index d825c43eb2d76..0000000000000 Binary files a/documentation/users-guide/pictures/para5.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para6.png b/documentation/users-guide/pictures/para6.png deleted file mode 100644 index 6e346b8e7fa97..0000000000000 Binary files a/documentation/users-guide/pictures/para6.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para7.png b/documentation/users-guide/pictures/para7.png deleted file mode 100644 index f73e117b4efab..0000000000000 Binary files a/documentation/users-guide/pictures/para7.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para8.png b/documentation/users-guide/pictures/para8.png deleted file mode 100644 index dcc7476f56675..0000000000000 Binary files a/documentation/users-guide/pictures/para8.png and /dev/null differ diff --git a/documentation/users-guide/pictures/para9.png b/documentation/users-guide/pictures/para9.png deleted file mode 100644 index b725ba74e46ae..0000000000000 Binary files a/documentation/users-guide/pictures/para9.png and /dev/null differ diff --git a/documentation/users-guide/pictures/rootlogo.png b/documentation/users-guide/pictures/rootlogo.png deleted file mode 100644 index 1ee93864f3f14..0000000000000 Binary files a/documentation/users-guide/pictures/rootlogo.png and /dev/null differ diff --git a/documentation/users-guide/pictures/spider1.png b/documentation/users-guide/pictures/spider1.png deleted file mode 100644 index ef012309d7dc9..0000000000000 Binary files a/documentation/users-guide/pictures/spider1.png and /dev/null differ diff --git a/documentation/users-guide/pictures/spider2.png b/documentation/users-guide/pictures/spider2.png deleted file mode 100644 index 4731d23c8c14f..0000000000000 Binary files a/documentation/users-guide/pictures/spider2.png and /dev/null differ diff --git a/documentation/users-guide/pictures/th2poly1.png b/documentation/users-guide/pictures/th2poly1.png deleted file mode 100644 index f38adc079ff2a..0000000000000 Binary files a/documentation/users-guide/pictures/th2poly1.png and /dev/null differ diff --git a/documentation/users-guide/template.tex b/documentation/users-guide/template.tex deleted file mode 100644 index e602e0c387f2a..0000000000000 --- a/documentation/users-guide/template.tex +++ /dev/null @@ -1,172 +0,0 @@ -\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$$if(papersize)$$papersize$,$endif$]{$documentclass$} -\usepackage[T1]{fontenc} -\usepackage{lmodern} -\usepackage{amssymb,amsmath} -\usepackage{ifxetex,ifluatex} -\usepackage{fixltx2e} % provides \textsubscript -\usepackage{makeidx} -\makeindex -% use upquote if available, for straight quotes in verbatim environments -\IfFileExists{upquote.sty}{\usepackage{upquote}}{} -\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex - \usepackage[utf8]{inputenc} -$if(euro)$ - \usepackage{eurosym} -$endif$ -\else % if luatex or xelatex - \usepackage{fontspec} - \ifxetex - \usepackage{xltxtra,xunicode} - \fi - \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} - \newcommand{\euro}{€} -$if(mainfont)$ - \setmainfont{$mainfont$} -$endif$ -$if(sansfont)$ - \setsansfont{$sansfont$} -$endif$ -$if(monofont)$ - \setmonofont{$monofont$} -$endif$ -$if(mathfont)$ - \setmathfont{$mathfont$} -$endif$ -\fi -% use microtype if available -\IfFileExists{microtype.sty}{\usepackage{microtype}}{} -$if(geometry)$ -\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} -$endif$ -$if(natbib)$ -\usepackage{natbib} -\bibliographystyle{plainnat} -$endif$ -$if(biblatex)$ -\usepackage{biblatex} -$if(biblio-files)$ -\bibliography{$biblio-files$} -$endif$ -$endif$ -$if(listings)$ -\usepackage{listings} -$endif$ -$if(lhs)$ -\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} -$endif$ -$if(highlighting-macros)$ -$highlighting-macros$ -$endif$ -$if(verbatim-in-note)$ -\usepackage{fancyvrb} -$endif$ -$if(tables)$ -\usepackage{longtable} -$endif$ -$if(graphics)$ -\usepackage{graphicx} -% We will generate all images so they have a width \maxwidth. This means -% that they will get their normal width if they fit onto the page, but -% are scaled down if they would overflow the margins. -\makeatletter -\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth -\else\Gin@nat@width\fi} -\makeatother -\let\Oldincludegraphics\includegraphics -\renewcommand{\includegraphics}[1]{\Oldincludegraphics[width=\maxwidth]{#1}} -$endif$ -\ifxetex - \usepackage[setpagesize=false, % page size defined by xetex - unicode=false, % unicode breaks when used with xetex - xetex]{hyperref} -\else - \usepackage[unicode=true]{hyperref} -\fi -\hypersetup{breaklinks=true, - bookmarks=true, - pdfauthor={$author-meta$}, - pdftitle={$title-meta$}, - colorlinks=true, - urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$, - linkcolor=$if(linkcolor)$$linkcolor$$else$magenta$endif$, - pdfborder={0 0 0}} -\urlstyle{same} % don't use monospace font for urls -$if(links-as-notes)$ -% Make links footnotes instead of hotlinks: -\renewcommand{\href}[2]{#2\footnote{\url{#1}}} -$endif$ -$if(strikeout)$ -\usepackage[normalem]{ulem} -% avoid problems with \sout in headers with hyperref: -\pdfstringdefDisableCommands{\renewcommand{\sout}{}} -$endif$ -\setlength{\parindent}{0pt} -\setlength{\parskip}{6pt plus 2pt minus 1pt} -\setlength{\emergencystretch}{3em} % prevent overfull lines -$if(numbersections)$ -\setcounter{secnumdepth}{5} -$else$ -\setcounter{secnumdepth}{0} -$endif$ -$if(verbatim-in-note)$ -\VerbatimFootnotes % allows verbatim text in footnotes -$endif$ -$if(lang)$ -\ifxetex - \usepackage{polyglossia} - \setmainlanguage{$mainlang$} -\else - \usepackage[$lang$]{babel} -\fi -$endif$ -$for(header-includes)$ -$header-includes$ -$endfor$ - -$if(title)$ -\title{$title$} -$endif$ -\author{$for(author)$$author$$sep$ \and $endfor$} -\date{$date$} - -\begin{document} -$if(title)$ -\maketitle -$endif$ - -$for(include-before)$ -$include-before$ - -$endfor$ -$if(toc)$ -{ -\hypersetup{linkcolor=black} -\setcounter{tocdepth}{$toc-depth$} -\tableofcontents -} -$endif$ -$body$ - -$if(natbib)$ -$if(biblio-files)$ -$if(biblio-title)$ -$if(book-class)$ -\renewcommand\bibname{$biblio-title$} -$else$ -\renewcommand\refname{$biblio-title$} -$endif$ -$endif$ -\bibliography{$biblio-files$} - -$endif$ -$endif$ -$if(biblatex)$ -\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ - -$endif$ -$for(include-after)$ -$include-after$ - -$endfor$ -\printindex -\end{document} diff --git a/documentation/users-guide/title.txt b/documentation/users-guide/title.txt deleted file mode 100644 index f44bbbc6baef5..0000000000000 --- a/documentation/users-guide/title.txt +++ /dev/null @@ -1,2 +0,0 @@ -% ROOT User's Guide -% The ROOT Team diff --git a/documentation/users-guide/warning.md b/documentation/users-guide/warning.md deleted file mode 100644 index 952a5554e5ef1..0000000000000 --- a/documentation/users-guide/warning.md +++ /dev/null @@ -1,12 +0,0 @@ -> ________________________________________________________________________________________ -> **WARNING:** -> This documentation is **not maintained anymore**. Some part might be obsolete or wrong, some -> part might be missing but still some valuable information can be found there. Instead please -> refer to the [ROOT Reference Guide](https://root.cern/doc/master/index.html) and the -> [ROOT Manual](https://root.cern/manual/). If you think some information should be imported -> in the [ROOT Reference Guide](https://root.cern/doc/master/index.html) or in the -> [ROOT Manual](https://root.cern/manual/), please post your request to the -> [ROOT Forum](https://root-forum.cern.ch) or via a -> [Github Issue](https://github.com/root-project/web/issues/new). -> -> ________________________________________________________________________________________ diff --git a/etc/html/HELP.html b/etc/html/HELP.html deleted file mode 100644 index 0d43d8634c166..0000000000000 --- a/etc/html/HELP.html +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - -Help for ROOT's Reference Guide - - - - - - - - -
-

Help for ROOT's Reference Guide

-
- -
- -

Parts of the Reference Guide

- -

Type Index

-All basic types and typedefs are documented in the Type Index. - -

Class Index

-All classes and namespaces are listed alphabetically in the Class Index, -along with a short info of what they are used for. -You can jump to a class's entry using the shortcuts ontop of the page. -They are optimized for quick access: they are distributed evenly, and short. -Classes are grouped in modules; these, too, are listed ontop of the list of classes. - -

Inheritance

-All classes along with their derived and base classes are shown in the -Class Hierarchy. -The documentation for each class also shows the inheritance diagram. -The class hierarchy is meant to give an overview of available classes -and their relations. - -

Modules

-

What they are

-Classes are grouped into modules. For ROOT, this is done on a per-directory basis: -each module corresponds to a sub-directory. In other cases one module might represent -one library. Either way, modules are meant to combine similar or related classes, -allowing users to find classes close by context. If you need some functionality that -you cannot find in a class you know, you might want to check for classes in the same -module - maybe one of them does what you need. - -

List of Modules

-Modules are listed ontop of the Class Index and as part -of the Library Dependencies Chart. - -

Modules' Library Dependencies

-Each module is assumed to be part of a library. The dependencies of libraries are -not only relevant for linking, but often reflect also the contextual dependencies. -The dependencies of all modules are shown in the -Library Dependencies Chart. - -

Class Reference

-Pages like the one for TH2 are -class references. They document the use and functionality of a class. - -

Sections

-Each class reference page has a class documentation, which documents what the class -can be used for, and gives hints on how to use it. This allows you to figure out -whether a certain class is appropriate for what you try to do. The page then lists -all available members; they define a class's functionality and its interaction with -your code. The next item is a tabbed set of charts, which allow you to study the -class's inheritance diagram, what members get inherited from where, and which members -are re-implemented, which files get indirectly included by including the class's -header, and which libraries this class depends on. The remainder of the page contains -the functions' documentation. And there is a little tool box floating around, which -gives you some display options and a link to this help page. - -We will now go through all these parts in detail. - -

Link Box

-On the top of the page you can find a list of links. The first line contains the current -"location", giving the home page, the module name, and the class name. -The second line links to generic pages, like ROOT's home page, the -Class Index, and the Class Hierarchy. -The last line allows you to jump to the sections of the current page and a colored -version of the class's header and source file. - -

Info Box

-There is a little info box, usually floating on the right side of the page -(update your browser if it's not). It shows the name of the class you are currently -looking at, which library you have to link against to get access to the class, and -which header file you have to #include. - -It also contains options that influence how -the list of members is displayed. you can show or hide non-public methods. If you -just want to use ROOT you should hide them - you cannot access protected or private -members anyway. And you can select whether member that are inherited from a base class -should be shown. Again, if you just want to use ROOT you should probably show them, -as you often want to use them whether they are defined in the current class or in one -of its base classes. Whatever you set these options to should be stored in a cookie, -so you will have the same setting next time you look at the class documentation. - -The two links in the bottom of the box get you to the top of the page and to this help -page. You can hide the info box by clicking on the little "-" in the top right corner -of the box, and show it again by clicking on the "+". - -

List of Data and Function Members

-

The central part of a class are its members. Some are available to you; some -are hidden from you, because they are only meant to be used internally. -As an example, a class might allow you to set, access, and print its values, or store -them into a file. -Because methods should have reasonable names, often the method name itself is already -a hint on what it does. -If you want to get a TNamed's -name, you will immediately see TNamed::GetName() in its list of functions. -A click on this name will send you to the documentation for the method. -If you enabled the display of inherited members you will see -some members with a class name prefix. It tells you where this method has been defined.

- -

Display Options

-The info box contains options that influence how -the list of members is displayed: you can e.g. show or hide non-public methods. If you -just want to use ROOT you should hide them - you cannot access protected or private -members anyway. And you can select whether member that are inherited from a base class -should be shown. Again, if you just want to use ROOT you should probably show them, -as you often want to use them whether they are defined in the current class or in one -of its base classes. Whatever you set these options to should be stored in a cookie, -so you will have the same setting next time you look at the class documentation. - -

Access (public / protected / private)

-Not all members are available to everyone (check any C++ introduction to learn why). -Public members have a green bar on their left, protected ones have a yellow one, and -private members are marked with a red bar. Of course you won't see any protected or -private members if you hide them in the display options. - -

Inheritance

-You can often access members of a class's base classes, just as if they are defined -in the derived class. A histogram, -for example, has a name, and you can access it using GetName() as defined in its base -class TNamed. If you want to see -all available members, and not just the ones defined in the current class, in the -display options. They will be prefixed with the name of -the class they are defined in. - -

Class Charts

-The class charts are shown in a tabbed box; click on the names ontop to select a tab. - -

Inheritance

-This chart shows the inheritance hierarchy for the current class. Arrows point to -base classes. You can click the classes to get to their reference page. - -

Inherited Members

-The second chart shows a list of all members of all base classes. You can see at what -level they are defined or at what level they are defined. Members that are accessible -(public) have a green background, protected ones have a yellow background, and private -members have a red background. Members with a dark gray background are re-implemented -or hidden by a derived class. - -

Includes

-The Includes chart shows which files are indirectly included by including the class's -header. Most headers will #include some files, so by #including that header you also -#include the #included files, and so on. A illegible chart often means you should -read a bit on the C++ trick known as "forward declaration". Including too many headers -has some nasty consequences, like compile time, additional dependencies, etc. - -

Libraries

-Each class is assumed to be in a library. That library might depend on other libraries. -The fourth chart shows the dependencies of these libraries. You will need to link against -all of these if you write your own program. - -

Member Function Documentation

-Each function should be documented by the developer of the class. The documentation can -contain HTML, pictures, and example code. It should explain what the function does, -what it expects as parameters, what it returns, and what can make it fail. Short functions -can have their source displayed. You can click on the function name to jump to a -colored version of the function's source. - -

 

-
- -Author: Axel Naumann
-Last update: 2007-01-12
-Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.
-
-

-This page has been hand crafted. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT. -

- - diff --git a/etc/html/ROOT.css b/etc/html/ROOT.css deleted file mode 100644 index 294654ff879a9..0000000000000 --- a/etc/html/ROOT.css +++ /dev/null @@ -1,715 +0,0 @@ -/* ROOT CSS, Axel 2007-02-07 */ - -/*** Generic layout ***/ -body { - font-family: Arial,Verdana,sans-serif; - color: inherit; - background-color: #8596AA; - min-width: 750px; - margin: 0; - padding: 20px 0; -} -#body_content { - background-color: #FFFFFF; - width: 818px; - font-size: 82%; - line-height: 130%; - margin: 0 auto; - padding: 3px 16px; -} - -/* links */ -a { - text-decoration: none; -} -a:link { - color: #336299; - background-color: inherit; - text-decoration: none; -} -a:visited { - color: #336299; - background-color: inherit; -} -a:active { - color: #336299; - background-color: inherit; - border: dotted 1px #0000ff; -} -a:hover { - color: #336299; - text-decoration: underline; -} - -/* headers */ -h1, h2, h3, h4 { - color: inherit; -} -h1 { - font-size: 2em; - line-height: 1.5em; - margin: 0; -} -h2 { - font-size: 1.3em; - margin: 1.5em 1.5em; -} -h3 { - font-size: 1em; -} - -#footer { - margin-top: 1em; - font-size: 75%; - line-height: 110%; - border-top: 1px solid #CCCCCC; - padding: 0.3em; -} -#footer em { - display: block; - font-style: normal; -} - -/* tabbed divs */ -div.tabs { - padding-left: 1em; - margin-top: 3em; - margin-left: 2em; -} -a.tab { - border-top: solid 1px Gray; - border-left: solid 1px Gray; - border-right: solid 1px Gray; - border-bottom: solid 0px Black; - color: #444444; - background-color: #eeeeee; - padding: 1px 0.4em 1px 0.4em; - margin-bottom: 1px; - position: relative; - top: -1px; -} -* html a.tab { - /* IE only, fix pos bug */ - top: -2px; -} -a.tab:hover { - color: inherit; -} -a.tabsel { - border-top: solid 2px Black; - border-left: solid 2px Black; - border-right: solid 2px Black; - border-bottom: solid 3px White; - padding: 1px 0.4em 0px 0.4em; - position: relative; - top: -1px; - background-color: White; - color: Black; - font-weight: bold; - font-style: normal; -} -* html a.itabsel { - /* IE only, fix pos bug */ - top: -2px; -} -a.tabsel:hover { - text-decoration: none; - cursor: default; -} -a.tabsel:active { - color: Black; - background-color: inherit; - border-left: solid 2px Black; - border-right: solid 2px Black; - border-top: solid 2px Black; - border-bottom: solid 3px White; -} -div.tabcontent { - border: solid 2px Black; - display: table; - margin: 0em 2em 0em 2em; - padding: 0.5em 0.5em 0.5em 0.5em; - background-color: #fff; -} -div.tabwidth { - width: 28em; - height: 0pt; -} -div.tabvisible, div.tabhidden { -} - -div.tabvisible { - display: block; - margin-left: auto; - margin-right: auto; -} -div.tabhidden { - display: none; - margin-left: auto; - margin-right: auto; -} - -div.clear { - clear: both; -} - -/* links on top of page */ -#root_header { - margin:0px -13px; - height:148px; -} -#root_header img { - margin: 10px; -} - -#toplinks { - font-size: 90%; - border-top: 1px solid #FFFFFF; - width: 844px; - color: #FFFFFF; - margin: 1px -13px 3px -13px; - background-color: #2E4A6B; - padding-bottom: 5px; -} -div.descrhead { - text-align:right; - padding: 0; - margin: 0; - height: 1.5em; -} -span.descrtitle { - display: inline-block; - width: 6em; - padding: 0 14px; - font-weight: bold; - white-space: nowrap; -} -div.descrheadcontent { - display: inline-block; - text-align: left; - margin: 0 auto 0 0; - padding: 0 0; - float: left; -} -a.descrheadentry { - color: #FFFFFF; - text-decoration: none; - margin: 0; - font-weight: lighter; - border: none; - border-left: solid 1px #dddddd; - padding: 0px 14px; - white-space: nowrap; - display: inline-block; - width: 100px; -} -a.descrheadentry:visited { - color: #dddddd; - text-decoration: inherit; -} -a.descrheadentry:hover { - color: #ffffff; - background-color: #336299; - text-decoration: none; -} -div.location { - clear: both; - margin-bottom: 0.5em; - padding-bottom: 0.5em; - padding-top: 3px; - font-size: 80%; -} - -/* convert */ -table.descrtitle { - width: 100%; -} -a.contextheadentry { - text-decoration: none; - font-size: small; - font-weight: normal; -} -a.contextheadentry:visited { - color: #FFFFFF; - background-color: inherit; - text-decoration: inherit; -} -a.contextheadentry:hover { - color: #FFFFFF; - background-color: #336299; - text-decoration: underline; -} -td.contextheadentry { - color: #FFFFFF; - background-color: inherit; - margin-left: 0.0em; - margin-right: 0.0em; - border-bottom: none; - padding-left: 0.3em; - padding-right: 0.3em; - width: 40%; - text-align: left; -} - -a.contextheadarrow { - font-size:xx-large; - text-decoration: none; - color: inherit; - padding-left: 0.3em; - padding-right: 0.3em; -} -a.contextheadarrow:hover { - color: #FFFFFF; - background-color: #336299; -} - -#contexttitle div { - margin-top: -0.9em; - margin-bottom: -0.5em; -} -#contexttitle a { - color: #FFFFFF; -} - -#contextheadentry_next { - border-left: dotted 1px #FFFFFF; - text-align: right; -} -#contextheadarrow_next { - border-left: none; -} -#divcontextheadarrow_up { - margin-top: -0.4em; -} -#contextheadarrow_up { - border-left: dotted 1px #FFFFFF; -} -#contextheadentry_up { - width: 20%; -} -#toplinks h1 { - font-size: x-large; - padding: 0.5em 0em 0em 0em; - margin: 0.3em 1em 0.1em 1em; -} - -/* TOC */ -div.toc { - font-weight: bold; - font-size: small; - border: solid 1px Gray; - margin-left: 3em; - padding-top: 1em; - padding-left: 1em; - padding-right: 2em; - float: left; - clear: left; -} -ul.toc { - font-weight: normal; - list-style: none; - padding-left: 2em; -} - - -/*** Index pages ***/ -a.linkeddoc { - padding-right: 3em; - text-align: center; - font-style: italic; -} -#furtherreading { - margin-left: 3em; - margin-bottom: 2em; -} - -#indx { - padding-left: 2em; - margin-left: 0px; -} -#indx li { - list-style: none; - padding: 0; - border: none; -} -#indx li.idxl0 { - background-color: #EEF4F9; -} -#indx span.typename { - display: inline-block; - font-weight: bold; - margin-left: 0em; - padding-right: 2em; - min-width: 10em; -} - -#indxShortX, #indxModules { - border: 1px solid #CCCCCC; - background-color: #F5F5E9; - margin: 4px 0; - color: #000000; - padding: 8px 2em; -} -#indxShortX h4, #indxModules h4 { - font-size: 1.2em; - line-height: 1.5em; - margin: 0; -} -#indxShortX a, #indxModules a { - font-weight: bold; - display: inline-block; - padding: 0px 0.5em; -} - -#searchform { - display: inline-block; -} - -#searchform input { - display: inline-block; - border: 1px solid #336699; - vertical-align: middle; - width: 12em; - font-size: 0.9em; -} - -#searchlink { - font-size: 0.8em; - vertical-align: middle; - background-color: ButtonFace; - border-style: outset; - border-width: 1px; - padding: 1px 8px 1px 8px; - text-decoration: none; - color: ButtonText; - margin: 0 0 0 0.1em; -} - -/*** Class doc pages ***/ -div.classdescr { - border-bottom: 3px solid #FEC201; - border-top: 3px solid #FEC201; - padding: 10px 15px 10px 54px; -} -div.classdescr pre { - margin: 0; - padding: 0; -} -div.code { - margin-bottom: 0.5em; - margin-top: 0.5em; - padding: 0.5em; - border: solid 1px #ffff77; - color: inherit; - background-color: #ffffdd; - float: left; -} - -table.inhtree { - color: inherit; - background-color: White; - border: solid 1px Black; - width: 97%; -} -#functions { - margin-top: 4em; - margin-left: 0em; - color: inherit; - background-color: White; - clear: both; -} -#datamembers { - margin-top: 4em; - margin-left: 0em; - margin-bottom: 6em; - color: inherit; - background-color: White; -} -div.access { - border-left: solid 3pt black; - padding-left: 1em; - margin-left: 0em; - margin-bottom: 1em; -} -#funcpubl { - border-left-color: #77ff77; -} -#datapubl { - border-left-color: #77ff77; -} -#enumpubl { - border-left-color: #77ff77; -} -#funcprot { - border-left-color: #ffff00; -} -#dataprot { - border-left-color: #ffff00; -} -#enumprot { - border-left-color: #ffff00; -} -#funcpriv { - border-left-color: #ff7777; -} -#datapriv { - border-left-color: #ff7777; -} -#enumpriv { - border-left-color: #ff7777; -} - -table.func, table.data /* but not table.data! */ { - width: 100%; -} -tr.func, tr.data { - white-space: nowrap; -} -tr.datainh { - display: none; - white-space: nowrap; -} -tr.funcinh { - display: none; - white-space: nowrap; -} -span.baseclass { - color: #aaaaaa; - font-weight: normal; -} -td.funcret, td.datatype { - text-align: right; - padding: 0px 0.5em 0px 0.5em; - margin: 0px 0px 0px 0px; - white-space: nowrap; - width: 10%; -} -a.funcname { - font-weight: bolder; - margin-right: 0.4em; -} -td.funcname { - white-space: normal; - text-indent: -2em; - padding: 0px 0px 0px 2em; - margin: 0px 0px 0px 0px; - width: 100%; - width: 80%; -} -span.funcprop -{ - margin-left: 1em; - background-color: #FFFFCC; - border: solid 1px #FFFF33; - font-size: 80%; - font-weight: bold; -} -td.dataname { - font-weight: bolder; - vertical-align: top; - padding: 0px 0.5em 0px 0px; - min-width: 10em; -} -td.datadesc { - padding: 0px 0px 0px 0.5em; - border-left: 2px solid #FEC201; - white-space: normal; - color: inherit; - background-color: #FFFFF6; - width: 70%; -} - -/* class charts */ -div.classcharts { - border: solid 2px Black; - display: table; - margin: 0em 2em 4em 2em; -} -div.classchartswidth { - width: 28em; - height: 0pt; -} -img.classcharts { - display: block; - border: none; - margin-left: auto; - margin-right: auto; -} - -/* function documentation */ -div.funcdoc { - width: 97%; - margin-bottom: 3em; - border-left: 0.3em solid #eeeeff; - padding: 0.1em 0.3em 0.3em 0.3em; - color: inherit; -} -div.funccomm { - border: solid 1px #cccccc; - padding-top: 0.5em; - padding-bottom: 0.5em; - padding-left: 0.5em; - background-color: White; - margin: 0.3em 0px 0.3em 0.5em; -} - -/* toolbox */ -#followpage { - font-size: small; - border: solid 2px Gray; - position: fixed; - top: 3em; - right: 1em; - z-index: 2; - color: Black; /*InfoText;*/ - background-color: #FFFFE1; /*InfoBackground;*/ - filter: alpha (opacity=20); - -moz-opacity: .2; - opacity: .2; -} -* html #followpage { - position: absolute; - float: right; - right: 1em; - top: 4em; - filter: alpha (opacity=100); - -moz-opacity: 1; - opacity: 1; -} -#followpage:hover { - filter: alpha (opacity=90); - -moz-opacity: .9; - opacity: .9; -} - -#followpagecontenthide { - display: none; -} -#followpagetitle { - font-size: inherit; - font-weight: normal; - margin-bottom: 0.3em; - border-bottom: solid 1px Gray; - background-color: Gray; - font-size: medium; - color: White; - text-align: center; - padding-right: 1.1em; -} -* html #followpagetitle { - width: auto; -} -#dispopt { - margin: 0.3em 0.3em 0px 0.3em; - padding-top: 0.3em; - border-top: solid 1px Gray; - padding-bottom: 0.3em; - border-bottom: solid 1px Gray; -} -#formdispopt { - margin: 0px 0.3em 0px 0.3em; -} -div.libinfo { - margin: 0px 0.3em 0px 0.3em; -} -#followlinks { - text-align: center; - margin: 0.3em 0.3em 0.3em 0.3em; -} -a.followpagedisp { - color: Black; - background-color: #cccccc; - width: 1em; - position: absolute; - right: 0.1em; - top: 0.1em; - font-weight: bold; - font-size: x-small; - font-family: Courier; - text-decoration: none; - padding-left: 0.3em; - padding-right: 0.3em; -} - -a.followpagedisp:hover { - background-color: White; -} - -#followpageshower { - display: none; - position: relative; - top: 0em; - left: 0em; -} -#followpagehider { - display: inline; -} -#followpagecontent { - display: block; -} - -img.latex { - vertical-align: middle; -} - -/* Source pages */ -span.comment, span.codecomment, span.keyword, span.cpp, span.string { - font-weight: normal; -} -span.codecomment, span.comment { - background-color: #eeeeee; - color: Green; -} -span.keyword { - color: Black; - background-color: inherit; -} -span.cpp { - color: Gray; - background-color: inherit; -} -span.string { - color: Teal; - background-color: inherit; -} -#codeAndLineNumbers { - margin-left: -32px; - font-size: 110%; -} -pre.listing { - margin: 5px 0px 0px 45px; - padding-left: 1.2em; - line-height: normal; - float: left; - height: 0; -} -div.linenums { - width: 0em; - display: block; -} -div.ln { - font-family: monospace; - line-height: normal; - width: 50px; - text-align: right; - height: 100%; - border-right: 1px solid #aaaaaa; -} -a.ln { - display: inline-block; - height: 100%; - text-decoration:none; - color: #CE9201; - font-size: 80%; - margin: 0; - padding: 0 0.2em 0 0; -} -span.lnfile { - font-size:1%; - display: inline-block; - overflow: hidden; - width: 1px; - color: #fff; - margin: 0; - padding: 0; -} diff --git a/etc/html/ROOT.js b/etc/html/ROOT.js deleted file mode 100644 index 1e613642164d5..0000000000000 --- a/etc/html/ROOT.js +++ /dev/null @@ -1,152 +0,0 @@ -function SetCSSValue(where,what,to){ - var r='cssRules'; - if(document.all && navigator.appName.indexOf('Opera')==-1) - r='rules'; - var i; - for(i=0;i0) cookietxt+=':'; - cookietxt+=val; - } - var ayear=new Date(); - ayear.setTime(ayear.getTime()+31536000000); - cookietxt+=";path=/;expires="+ayear.toUTCString(); - document.cookie=cookietxt; -} -function CBChanged(cb){ - if(cb.id=='dispoptCBInh') { - SetCSSValue('tr.funcinh','display',cb.checked?'':'none'); - SetCSSValue('tr.datainh','display',cb.checked?'':'none'); - } else if(cb.id=='dispoptCBPub') { - SetCSSValue('#funcprot','display',cb.checked?'':'none'); - SetCSSValue('#funcpriv','display',cb.checked?'':'none'); - SetCSSValue('#dataprot','display',cb.checked?'':'none'); - SetCSSValue('#datapriv','display',cb.checked?'':'none'); - SetCSSValue('#enumprot','display',cb.checked?'':'none'); - SetCSSValue('#enumpriv','display',cb.checked?'':'none'); - } - UpdateCookie(); -} -function SetImg(name, file) { - var img=document.getElementById(name); - var src=img.src; - var posFile=src.lastIndexOf('/'); - var numSlashes=file.split('/').length - 1; - for (var i=0; i'); - document.writeln('+'); - document.writeln('
' + title + '
'); - document.writeln('-'); - if (lib.length || incl.length) { - document.writeln('
'); - if (lib.length) - document.writeln('library: ' + lib + '
'); - if (incl.length) - document.writeln('#include "' + incl + '"
'); - document.writeln('
'); - } - document.writeln('
Display options:
'); - document.writeln('
'); - document.writeln('Show inherited
'); - document.writeln('Show non-public
'); - document.writeln('
'); - document.writeln('
'); - document.writeln(''); - document.writeln('
'); - document.writeln('
'); -} diff --git a/etc/html/footer.html b/etc/html/footer.html deleted file mode 100644 index dde53b7250d67..0000000000000 --- a/etc/html/footer.html +++ /dev/null @@ -1,10 +0,0 @@ -
- - - - - diff --git a/etc/html/header.html b/etc/html/header.html deleted file mode 100644 index 357c7103e1b01..0000000000000 --- a/etc/html/header.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - -%TITLE% - - - - - - - -
-
diff --git a/etc/html/saveScriptOutput.C b/etc/html/saveScriptOutput.C deleted file mode 100644 index 2b2c71bc92c93..0000000000000 --- a/etc/html/saveScriptOutput.C +++ /dev/null @@ -1,90 +0,0 @@ -#include "TString.h" -#include "TSystem.h" -#include "TGWindow.h" -#include "TGClient.h" -#include "TClass.h" -#include "THashList.h" -#include "TROOT.h" -#include "TInterpreter.h" -#include "TRootCanvas.h" -#include "TCanvas.h" -#include "TVirtualViewer3D.h" -#include "TEnv.h" -#include "TVirtualX.h" - -int saveScriptOutput(const char* script, const char* outdir, Bool_t compiled) -{ - // Run script and save all windows to - // outdir/script_0.png, outdir/script_1.png, ... - - enum EErrorCodes { - kSuccess, - kScriptDirNotFound, - kCannotRunScript, - kOutDirNotFound, - kNumErrorCodes - }; - - TString pwd(gSystem->pwd()); - if (!gSystem->cd(gSystem->GetDirName(script))) - return kScriptDirNotFound; - Int_t err = 0; - TString cmd(".x "); - cmd += gSystem->BaseName(script); - if (compiled) - cmd += "+"; - if (!gROOT->IsBatch()) - gVirtualX->Sync(1); - - // save current interpreter context to avoid gROOT->Reset() - // in the script to cause havoc by wiping everything away - gInterpreter->SaveContext(); - gInterpreter->SaveGlobalsContext(); - - gROOT->ProcessLine(cmd, &err); - if (err != TInterpreter::kNoError) - return kCannotRunScript; - - gSystem->cd(pwd); - if (!gSystem->cd(outdir)) - return kOutDirNotFound; - - UInt_t nCanvases = 0; - if (gClient) { - TClass* clRootCanvas = TClass::GetClass("TRootCanvas"); - TClass* clGMainFrame = TClass::GetClass("TGMainFrame"); - TGWindow* win = 0; - TIter iWin(gClient->GetListOfWindows()); - while((win = (TGWindow*)iWin())) { - const TObject* winGetParent = win->GetParent(); - Bool_t winIsMapped = kFALSE; - if (winGetParent == gClient->GetDefaultRoot()) - winIsMapped = win->IsMapped(); - if (winIsMapped && win->InheritsFrom(clGMainFrame)) { - win->MapRaised(); - Bool_t isRootCanvas = win->InheritsFrom(clRootCanvas); - Bool_t hasEditor = false; - if (isRootCanvas) { - hasEditor = ((TRootCanvas*)win)->HasEditor(); - } - if (isRootCanvas && !hasEditor) { - TVirtualPad* pad = ((TRootCanvas*)win)->Canvas(); - if (!pad->HasViewer3D() || pad->GetViewer3D()->InheritsFrom("TViewer3DPad")) { - pad->SaveAs(TString::Format("%s_%d.png", gSystem->BaseName(script), nCanvases++)); - } - } else - win->SaveAs(TString::Format("%s_%d.png", gSystem->BaseName(script), nCanvases++)); - } - } - } else { - // no gClient - TVirtualPad* pad = 0; - TIter iCanvas(gROOT->GetListOfCanvases()); - while ((pad = (TVirtualPad*) iCanvas())) { - pad->SaveAs(TString::Format("%s_%d.png", gSystem->BaseName(script), nCanvases++)); - } - } - if (!gROOT->IsBatch() && !gEnv->GetValue("X11.Sync", 0)) - gVirtualX->Sync(0); - return kSuccess; -} diff --git a/etc/html/shadow.gif b/etc/html/shadow.gif deleted file mode 100644 index 5b0bab7722877..0000000000000 Binary files a/etc/html/shadow.gif and /dev/null differ diff --git a/etc/html/shadowAlpha.png b/etc/html/shadowAlpha.png deleted file mode 100644 index 86acff90cab72..0000000000000 Binary files a/etc/html/shadowAlpha.png and /dev/null differ diff --git a/etc/plugins/TFile/P010_TWebFile.C b/etc/plugins/TFile/P010_TWebFile.C index 662b2661736a5..ef9260032ab12 100644 --- a/etc/plugins/TFile/P010_TWebFile.C +++ b/etc/plugins/TFile/P010_TWebFile.C @@ -1,5 +1,5 @@ void P010_TWebFile() { - gPluginMgr->AddHandler("TFile", "^http[s]?:", "TWebFile", - "Net", "TWebFile(const char*,Option_t*)"); + gPluginMgr->AddHandler("TFile", "^http[s]?:", "ROOT::Deprecated::TWebFile", + "Net", "ROOT::Deprecated::TWebFile(const char*,Option_t*)"); } diff --git a/etc/plugins/TFile/P150_TS3WebFile.C b/etc/plugins/TFile/P150_TS3WebFile.C index 85f28d17b8bd3..14f5434b0bfeb 100644 --- a/etc/plugins/TFile/P150_TS3WebFile.C +++ b/etc/plugins/TFile/P150_TS3WebFile.C @@ -1,11 +1,11 @@ void P150_TS3WebFile() { - gPluginMgr->AddHandler("TFile", "^[a]?s3:", "TS3WebFile", - "Net", "TS3WebFile(const char*,Option_t*)"); - gPluginMgr->AddHandler("TFile", "^s3http[s]?:", "TS3WebFile", - "Net", "TS3WebFile(const char*,Option_t*)"); - gPluginMgr->AddHandler("TFile", "^gs:", "TS3WebFile", - "Net", "TS3WebFile(const char*,Option_t*)"); - gPluginMgr->AddHandler("TFile", "^gshttp[s]?:", "TS3WebFile", - "Net", "TS3WebFile(const char*,Option_t*)"); + gPluginMgr->AddHandler("TFile", "^[a]?s3:", "ROOT::Deprecated::TS3WebFile", + "Net", "ROOT::Deprecated::TS3WebFile(const char*,Option_t*)"); + gPluginMgr->AddHandler("TFile", "^s3http[s]?:", "ROOT::Deprecated::TS3WebFile", + "Net", "ROOT::Deprecated::TS3WebFile(const char*,Option_t*)"); + gPluginMgr->AddHandler("TFile", "^gs:", "ROOT::Deprecated::TS3WebFile", + "Net", "ROOT::Deprecated::TS3WebFile(const char*,Option_t*)"); + gPluginMgr->AddHandler("TFile", "^gshttp[s]?:", "ROOT::Deprecated::TS3WebFile", + "Net", "ROOT::Deprecated::TS3WebFile(const char*,Option_t*)"); } diff --git a/geom/geom/doc/index.md b/geom/geom/doc/index.md index 386f1f72c494a..c4c779f12cb5f 100644 --- a/geom/geom/doc/index.md +++ b/geom/geom/doc/index.md @@ -292,7 +292,7 @@ represented by TGeoNode objects. This hierarchy is a tree since a node can have only one parent and several daughters. For a better understanding of the hierarchy, have a look at TGeoManage. -Just close now the `X3D` window and focus at the wire frame picture +Just close now the external 3D viewer and focus at the wire frame picture drawn in a pad. Activate Options/Event Status. Moving the mouse in the pad, you will notice that objects are sometimes changing color to red. Volumes are highlighted in this way whenever the mouse pointer is close @@ -2269,8 +2269,7 @@ and volume hierarchies. The main component of the visualization system is volume primitive painting in a ROOT pad. Starting from this one, several specific options -or subsystems are available, like: X3D viewing using hidden line and -surface removal algorithms, OpenGL viewing\* or ray tracing. +or subsystems are available, like: OpenGL viewing\* or ray tracing. The method TGeoManager::GetGeomPainter() loads the painting library in memory. @@ -3153,4 +3152,3 @@ the volume editor interface to: - [Presentation at ROOT 2007](http://indico.cern.ch/materialDisplay.py?contribId=35&materialId=slides&confId=13356) See also [the use of the geometry classes in AliROOT package of ALICE](https://alice-offline.web.cern.ch/AliRoot/Manual.html). - diff --git a/geom/geom/src/TGeoManager.cxx b/geom/geom/src/TGeoManager.cxx index 21fd28ce7805c..3bb85ca845789 100644 --- a/geom/geom/src/TGeoManager.cxx +++ b/geom/geom/src/TGeoManager.cxx @@ -2716,7 +2716,6 @@ void TGeoManager::SaveAttributes(const char *filename) } out << " // draw top volume with new settings" << std::endl; out << " top->Draw();" << std::endl; - out << " gPad->x3d();" << std::endl; out << "}" << std::endl; out.close(); } diff --git a/geom/geompainter/src/TGeoPainter.cxx b/geom/geompainter/src/TGeoPainter.cxx index 08330d4af1ac1..d98e78105a79f 100644 --- a/geom/geompainter/src/TGeoPainter.cxx +++ b/geom/geompainter/src/TGeoPainter.cxx @@ -49,13 +49,21 @@ using TBuffer3D mechanism. #include "TMath.h" #include "TVirtualGeoChecker.h" -#include "X3DBuffer.h" - #include "TBuffer3D.h" #include "TBuffer3DTypes.h" #include "TVirtualViewer3D.h" #include "TVirtualX.h" +#include + +namespace { + +bool IsX3DViewer(const TVirtualViewer3D *viewer) +{ + return viewer && viewer->IsA() && std::strcmp(viewer->IsA()->GetName(), "TViewerX3D") == 0; +} + +} // namespace //////////////////////////////////////////////////////////////////////////////// /// Default constructor. @@ -115,9 +123,10 @@ TGeoPainter::~TGeoPainter() void TGeoPainter::AddSize3D(Int_t numpoints, Int_t numsegs, Int_t numpolys) { - gSize3D.numPoints += numpoints; - gSize3D.numSegs += numsegs; - gSize3D.numPolys += numpolys; + // Legacy no-op kept for the obsolete x3d sizing interface. + (void)numpoints; + (void)numsegs; + (void)numpolys; } //////////////////////////////////////////////////////////////////////////////// /// Create a primary TGeoTrack. @@ -938,6 +947,11 @@ void TGeoPainter::DrawCurrentPoint(Int_t color) return; if (!gPad->GetView()) return; + + TVirtualViewer3D *viewer = gPad->GetViewer3D(); + if (!viewer || IsX3DViewer(viewer)) + return; + TPolyMarker3D *pm = new TPolyMarker3D(); pm->SetMarkerColor(color); const Double_t *point = fGeoManager->GetCurrentPoint(); diff --git a/geom/geompainter/src/TGeoTrack.cxx b/geom/geompainter/src/TGeoTrack.cxx index cd40e454f590e..87a5318fe33af 100644 --- a/geom/geompainter/src/TGeoTrack.cxx +++ b/geom/geompainter/src/TGeoTrack.cxx @@ -32,7 +32,6 @@ of all tracks that will be deleted on destruction of gGeoManager. */ - //////////////////////////////////////////////////////////////////////////////// /// Default constructor. @@ -525,20 +524,13 @@ void TGeoTrack::PaintMarker(Double_t *point, Option_t *) //////////////////////////////////////////////////////////////////////////////// /// Paint this track with its current attributes. -void TGeoTrack::PaintTrack(Option_t *option) +void TGeoTrack::PaintTrack(Option_t * /*option*/) { // Check whether there is some 3D view class for this TPad // TPadView3D *view3D = (TPadView3D*)gPad->GetView3D(); // if (view3D) view3D->PaintGeoTrack(this,option); // to be implemented - // Check if option is 'x3d'. NOTE: This is a simple checking - // but since there is no other - // options yet, this works fine. - TString opt(option); - opt.ToLower(); TObject::SetBit(kGeoPDrawn, kFALSE); - if (opt.Contains("x")) - return; Int_t np = fNpoints >> 2; Int_t imin = 0; Int_t imax = np - 1; diff --git a/geom/webviewer/inc/ROOT/RGeomData.hxx b/geom/webviewer/inc/ROOT/RGeomData.hxx index f940c7374453b..da1699a9e679c 100644 --- a/geom/webviewer/inc/ROOT/RGeomData.hxx +++ b/geom/webviewer/inc/ROOT/RGeomData.hxx @@ -109,6 +109,8 @@ public: // should be here, one needs virtual table for correct streaming of RRootBrowserReply ~RGeoItem() override = default; + void SetLogicalVisibility(int logicalVis) { vis = logicalVis; } + void SetPhysicalVisibility(int physicalVis) { pvis = physicalVis; } void SetTop(bool on = true) { top = on; } }; @@ -296,6 +298,10 @@ class RGeomDescription { int IsPhysNodeVisible(const std::vector &stack); + virtual bool IsFullModelStreamedAtOnce() const; + + virtual void RefineGeoItem(RGeoItem &item, const std::vector &stack); + /** clear drawing data without locking mutex */ void _ClearDrawData() { @@ -305,6 +311,7 @@ class RGeomDescription { public: RGeomDescription() = default; + virtual ~RGeomDescription() = default; void AddSignalHandler(const void *handler, RGeomSignalFunc_t func); diff --git a/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx b/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx index b1b685eeeedd9..afd8659c20b5e 100644 --- a/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx +++ b/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx @@ -30,7 +30,7 @@ protected: RGeomDescription &fDesc; /// fWebWindow; /// & /* stack */) +{ + // do nothing by default, placeholder for derived classes +} + + +///////////////////////////////////////////////////////////////////////////////// +/// Decide if the whole model is streamed at once +/// Function is called from ProcessBrowserRequest + +bool RGeomDescription::IsFullModelStreamedAtOnce() const +{ + return GetNumNodes() < (IsPreferredOffline() ? 1000000 : 1000); +} + ///////////////////////////////////////////////////////////////////// /// Find description object for requested shape /// If not exists - will be created @@ -781,7 +801,7 @@ std::string RGeomDescription::ProcessBrowserRequest(const std::string &msg) if (!request) return res; - if (request->path.empty() && (request->first == 0) && (GetNumNodes() < (IsPreferredOffline() ? 1000000 : 1000))) { + if (request->path.empty() && (request->first == 0) && IsFullModelStreamedAtOnce()) { std::vector vect(fDesc.size(), nullptr); @@ -830,6 +850,9 @@ std::string RGeomDescription::ProcessBrowserRequest(const std::string &msg) temp_nodes.back().SetExpanded(true); if (stack == fSelectedStack) temp_nodes.back().SetTop(true); + + RefineGeoItem(temp_nodes.back(), stack); + request->number--; if (!stack.empty()) diff --git a/graf2d/asimage/CMakeLists.txt b/graf2d/asimage/CMakeLists.txt index 87e27bd490b2f..3b5188c126edb 100644 --- a/graf2d/asimage/CMakeLists.txt +++ b/graf2d/asimage/CMakeLists.txt @@ -9,6 +9,8 @@ # @author Pere Mato, CERN ############################################################################ +add_subdirectory(src/libAfterImage) + ROOT_STANDARD_LIBRARY_PACKAGE(ASImage NO_INSTALL_HEADERS HEADERS @@ -23,7 +25,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ASImage DICTIONARY_OPTIONS -writeEmptyRootPCM LIBRARIES - ${AFTERIMAGE_LIBRARIES} + libAfterImage ${ASEXTRA_LIBRARIES} ${FREETYPE_LIBRARIES} ${X11_LIBRARIES} @@ -32,12 +34,12 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ASImage Core Graf Postscript - BUILTINS - AFTERIMAGE ) -target_include_directories(ASImage SYSTEM PRIVATE ${FREETYPE_INCLUDE_DIRS} ${AFTERIMAGE_INCLUDE_DIR} ${X11_INCLUDE_DIR}) -target_link_libraries(ASImage PRIVATE JPEG::JPEG PNG::PNG GIF::GIF) +target_link_libraries(ASImage PRIVATE JPEG::JPEG PNG::PNG GIF::GIF libAfterImage Freetype::Freetype) +if (x11) + target_link_libraries(ASImage PRIVATE X11::X11) +endif() ROOT_STANDARD_LIBRARY_PACKAGE(ASImageGui NO_INSTALL_HEADERS @@ -50,7 +52,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ASImageGui DICTIONARY_OPTIONS -writeEmptyRootPCM LIBRARIES - ${AFTERIMAGE_LIBRARIES} + libAfterImage ${ASEXTRA_LIBRARIES} ${FREETYPE_LIBRARIES} ${X11_LIBRARIES} @@ -60,7 +62,9 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ASImageGui ASImage ) -target_include_directories(ASImageGui SYSTEM PRIVATE ${FREETYPE_INCLUDE_DIRS} ${AFTERIMAGE_INCLUDE_DIR} ${X11_INCLUDE_DIR}) -target_link_libraries(ASImageGui PRIVATE JPEG::JPEG PNG::PNG GIF::GIF) +target_link_libraries(ASImageGui PRIVATE JPEG::JPEG PNG::PNG GIF::GIF libAfterImage Freetype::Freetype) +if (x11) + target_link_libraries(ASImageGui PRIVATE X11::X11) +endif() ROOT_INSTALL_HEADERS() diff --git a/graf2d/asimage/README b/graf2d/asimage/README index 4b1eaf725092c..b3babf9dc65e6 100644 --- a/graf2d/asimage/README +++ b/graf2d/asimage/README @@ -1,80 +1,5 @@ -The package libAfterImage has been imported from its official repository using the command: +Originally, the package libAfterImage was imported from its official repository using the command: cvs -d :pserver:anonymous@cvs.aftercode.net:/home/cvsroot checkout afterstep-stable/libAfterImage -This command download the source in: - - afterstep-stable/libAfterImage - -To get the updates for this package it is enough to do "cvs update" from this directory. - -To import libAfterImage into the ROOT svn repository we use the following command script: - - cd ~/afterstep-stable/libAfterImage - cvs update - cd /tmp - cp -rf ~/afterstep-stable/libAfterImage . - cd libAfterImage - rm -f Makefile config.status afterimage-libs config.log - rm -rf apps aftershow config.h - rm -rf ./libpng/CVS ./CVS ./win32/CVS ./libungif/CVS ./libjpeg/CVS ./zlib/CVS - cd libAfterImage - cp -R * $ROOTSYS/graf2d/asimage/src/libAfterImage - cd /tmp - rm -r libAfterImage - -Some files have been modified compare to the official libAfterImage version: - - config.h.in has been modified in order to use freetype from the ROOT - repository. - - libjpeg/jcmainct.c libjpeg/jdmainct.c have been modified to avoid a - compilation warning. These two pieces of code contain a variable called - "main" (some compiler do not like this). This variable name has been - changed to "mainptr". - - libjpeg/jmorecfg.h generated a warning on Windows: "a benign redifinition". - This warning has been disabled. - - libjpeg/jconfig.h: disable INLINE definition. - - libjpeg/jidctred.c: removed from repository (replaced by jidctint.c) - - libjpeg/jmorecfg.h and libjpeg/jconfig.h: fix a problem with boolean. - - configure.in: support clang++ by removing some warnings. - - libpng/pngpriv.h: fp.h was moved into math.h. This fix was originated by G. Eullisse - ALICE (April 2025) - - configure: - - has been modified to look at the ".dylib" file extension to find - the X11 libraries. This is needed on the Mac Leopard system. - - the compiling option -Winline has been removed because it produced many - warnings with gcc 4.3. - - support clang++ by removing some warnings. - - libAfterImage.mak: - Remove the word "Warning" in the message - "Warning: cannot find "libAfterImage.dep" to prevent to SPI - nightly build to issue an error. - - import.c: to fix the warning (on SLC5): - "warning: dereferencing type-punned pointer will break strict-aliasing rules" - - import.c and ungif.c (Ubuntu gcc 4.4): - "warning: ignoring return value of 'fread', declared with attribute warn_unused_result" - - export.c: to fix a warning on Open Solaris: - "initializer will be sign-extended: -1" - - export.c and import.c: - OSX Lion comes with builtin libpng 1.5.1 which obsoletes some 1.2 constructs - - asimage.c, char2uni.c, export.c, imencdec.c: - - fix a warning with clang: - "comparison of unsigned enum expression < 0 is always false" - -Note: -The file afterbase.h gets autogenerated by configure from afterbase.h.in -if afterbase.h.in has not changed, afterbase.h remains unchanged. - +Most files were modified and the build system adapted, compared to the official (obsolete) libAfterImage version. diff --git a/graf2d/asimage/doc/index.md b/graf2d/asimage/doc/index.md index 18b28e3c218e6..dfba94734e0e8 100644 --- a/graf2d/asimage/doc/index.md +++ b/graf2d/asimage/doc/index.md @@ -2,7 +2,7 @@ \ingroup Graphics2D \brief Classes interfacing to libAfterImage. - - [libAfterImage Imaging Library.](http://www.afterstep.org/afterimage/index.php) + - Originally forked from [libAfterImage Imaging Library](http://www.afterstep.org/afterimage/index.php), now self-maintained. - Several tutorials demonstrate how to use images in ROOT: - rose_image.C shows how to draw an image in a pad. - galaxy_image.C illustrates the TASImage class and an image editor. diff --git a/graf2d/asimage/inc/TASImage.h b/graf2d/asimage/inc/TASImage.h index d38433a2b0457..358b59a68e35b 100644 --- a/graf2d/asimage/inc/TASImage.h +++ b/graf2d/asimage/inc/TASImage.h @@ -71,12 +71,14 @@ class TASImage : public TImage { static ASVisual *fgVisual; ///< pointer to visual structure static Bool_t fgInit; ///< global flag to init afterimage only once + static Bool_t fgBatch; ///< global flag to signal if batch mode is active ie fgVisual->dpy was set to nullptr EImageFileTypes GetFileType(const char *ext); void MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas = kTRUE); void MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas = kTRUE); static Bool_t InitVisual(); + Bool_t InitImage(const char *caller); public: TASImage(); diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx index 6ea60a788019f..dedeff20eb1f7 100644 --- a/graf2d/asimage/src/TASImage.cxx +++ b/graf2d/asimage/src/TASImage.cxx @@ -107,9 +107,8 @@ ROOT tutorials: `$ROOTSYS/tutorials/visualisation/image/` #endif # include #else -# include -# include # define X_DISPLAY_MISSING 1 +# include #endif # include # include @@ -123,6 +122,7 @@ extern "C" { ASVisual *TASImage::fgVisual = nullptr; Bool_t TASImage::fgInit = kFALSE; +Bool_t TASImage::fgBatch = kFALSE; static ASFontManager *gFontManager = nullptr; static unsigned long kAllPlanes = ~0; @@ -485,7 +485,7 @@ const char *TASImage::TypeFromMagicNumber(const char *file) void TASImage::ReadImage(const char *filename, EImageFileTypes /*type*/) { if (!InitVisual()) { - Warning("Scale", "Visual not initiated"); + Warning("ReadImage", "Visual not initiated"); return; } @@ -1534,7 +1534,9 @@ void TASImage::Paint(Option_t *option) int tox = expand ? 0 : int(gPad->UtoPixel(1.) * gPad->GetLeftMargin()); int toy = expand ? 0 : int(gPad->VtoPixel(0.) * gPad->GetTopMargin()); - if (!gROOT->IsBatch()) { + auto ps = gPad->GetPainter()->GetPS(); + + if (!ps) { Window_t wid = (Window_t)gVirtualX->GetWindowID(gPad->GetPixmapID()); Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, tox, toy); @@ -1559,15 +1561,13 @@ void TASImage::Paint(Option_t *option) pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1), min, max, ndiv, "+L"); } - } - - // loop over pixmap and draw image to PostScript - if (gVirtualPS) { + } else { + // loop over pixmap and draw image to PostScript Bool_t paint_as_png = kFALSE; - if (gVirtualPS->InheritsFrom("TImageDump")) { // PostScript is asimage - TImage *dump = (TImage *)gVirtualPS->GetStream(); + if (ps->InheritsFrom("TImageDump")) { // PostScript is asimage + TImage *dump = (TImage *)ps->GetStream(); if (!dump) return; dump->Merge(fScaledImage ? fScaledImage : this, "alphablend", gPad->XtoAbsPixel(0), gPad->YtoAbsPixel(1)); @@ -1589,15 +1589,15 @@ void TASImage::Paint(Option_t *option) min, max, ndiv, "+L"); } return; - } else if (gVirtualPS->InheritsFrom("TPDF")) { + } else if (ps->InheritsFrom("TPDF")) { Warning("Paint", "PDF not implemented yet"); return; - } else if (gVirtualPS->InheritsFrom("TSVG")) { + } else if (ps->InheritsFrom("TSVG")) { paint_as_png = kTRUE; } - Double_t dx = gPad->GetX2()-gPad->GetX1(); - Double_t dy = gPad->GetY2()-gPad->GetY1(); + Double_t dx = gPad->GetX2() - gPad->GetX1(); + Double_t dy = gPad->GetY2() - gPad->GetY1(); Double_t x1, x2, y1, y2; if (expand) { @@ -1613,10 +1613,10 @@ void TASImage::Paint(Option_t *option) } // get special color cell to be reused during image printing - gVirtualPS->SetFillColor(TColor::GetColor((Float_t) 1., (Float_t) 1., (Float_t) 1.)); - gVirtualPS->SetFillStyle(1001); + ps->SetFillColor(TColor::GetColor((Float_t) 1., (Float_t) 1., (Float_t) 1.)); + ps->SetFillStyle(1001); - gVirtualPS->CellArrayBegin(image->width, image->height, x1, x2, y1, y2); + ps->CellArrayBegin(image->width, image->height, x1, x2, y1, y2); if (paint_as_png) { char *buffer = nullptr; @@ -1628,7 +1628,7 @@ void TASImage::Paint(Option_t *option) if (!params.png.compression) params.png.compression = -1; if (ASImage2PNGBuff(image, (CARD8 **)&buffer, &size, ¶ms)) { - gVirtualPS->CellArrayPng(buffer, size); + ps->CellArrayPng(buffer, size); free(buffer); } } else { @@ -1638,13 +1638,13 @@ void TASImage::Paint(Option_t *option) for (Int_t yt = 0; yt < (Int_t)image->height; yt++) { imdec->decode_image_scanline(imdec); for (Int_t xt = 0; xt < (Int_t)image->width; xt++) - gVirtualPS->CellArrayFill(imdec->buffer.red[xt], - imdec->buffer.green[xt], - imdec->buffer.blue[xt]); + ps->CellArrayFill(imdec->buffer.red[xt], + imdec->buffer.green[xt], + imdec->buffer.blue[xt]); } stop_image_decoding(&imdec); } - gVirtualPS->CellArrayEnd(); + ps->CellArrayEnd(); // print the color bar if (grad_im) { @@ -1654,8 +1654,8 @@ void TASImage::Paint(Option_t *option) x2 = x1 + xconv; y2 = gPad->AbsPixeltoY(pal_Ay); y1 = y2 - yconv; - gVirtualPS->CellArrayBegin(grad_im->width, grad_im->height, - x1, x2, y1, y2); + ps->CellArrayBegin(grad_im->width, grad_im->height, + x1, x2, y1, y2); if (paint_as_png) { char *buffer = nullptr; @@ -1668,7 +1668,7 @@ void TASImage::Paint(Option_t *option) params.png.compression = -1; if (ASImage2PNGBuff(grad_im, (CARD8 **)&buffer, &size, ¶ms)) { - gVirtualPS->CellArrayPng(buffer, size); + ps->CellArrayPng(buffer, size); free(buffer); } } else { @@ -1678,13 +1678,13 @@ void TASImage::Paint(Option_t *option) for (Int_t yt = 0; yt < (Int_t)grad_im->height; yt++) { imdec->decode_image_scanline(imdec); for (Int_t xt = 0; xt < (Int_t)grad_im->width; xt++) - gVirtualPS->CellArrayFill(imdec->buffer.red[xt], - imdec->buffer.green[xt], - imdec->buffer.blue[xt]); + ps->CellArrayFill(imdec->buffer.red[xt], + imdec->buffer.green[xt], + imdec->buffer.blue[xt]); } stop_image_decoding(&imdec); } - gVirtualPS->CellArrayEnd(); + ps->CellArrayEnd(); // values of palette TGaxis axis; @@ -1693,6 +1693,7 @@ void TASImage::Paint(Option_t *option) double max = fMaxValue; axis.SetLineColor(1); // draw black ticks Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w); + // TODO: provide PaintAxisOn method axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h), pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1), min, max, ndiv, "+L"); @@ -1977,12 +1978,12 @@ void TASImage::Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd, UInt_t toWidth, UInt_t toHeight) { if (!IsValid()) { - Warning("Scale", "Image not initiated"); + Warning("Slice", "Image not initiated"); return; } if (!InitVisual()) { - Warning("Scale", "Visual not initiated"); + Warning("Slice", "Visual not initiated"); return; } @@ -2225,52 +2226,65 @@ void TASImage::GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h) const Bool_t TASImage::InitVisual() { - Bool_t inbatch = fgVisual && (fgVisual->dpy == (void*)1); // was in batch - Bool_t noX = gROOT->IsBatch() || gVirtualX->InheritsFrom("TGWin32"); + Bool_t noX = gROOT->IsBatch() || !gVirtualX->InheritsFrom("TGX11"); - // was in batch, but switched to gui - if (inbatch && !noX) { - destroy_asvisual(fgVisual, kFALSE); - fgVisual = nullptr; - } - - if (fgVisual && fgVisual->dpy) { // already initialized + if (fgVisual && (noX == fgBatch)) return kTRUE; - } - // batch or win32 mode - if (!fgVisual && noX) { - fgVisual = create_asvisual(nullptr, 0, 0, nullptr); - fgVisual->dpy = (Display*)1; //fake (not used) - return kTRUE; - } + if (fgVisual) + destroy_asvisual(fgVisual, kFALSE); + fgVisual = nullptr; + fgBatch = false; #ifndef WIN32 -#ifdef R__HAS_COCOA - fgVisual = create_asvisual(nullptr, 0, 0, nullptr); - fgVisual->dpy = (Display*)1; //fake (not used) -#else +#ifndef R__HAS_COCOA Display *disp = (Display*) gVirtualX->GetDisplay(); Int_t screen = gVirtualX->GetScreen(); Int_t depth = gVirtualX->GetDepth(); Visual *vis = (Visual*) gVirtualX->GetVisual(); Colormap cmap = (Colormap) gVirtualX->GetColormap(); - if (!vis || cmap == 0) { - fgVisual = create_asvisual(nullptr, 0, 0, nullptr); - } else { + if (vis && cmap) fgVisual = create_asvisual_for_id(disp, screen, depth, XVisualIDFromVisual(vis), cmap, nullptr); - } #endif -#else - fgVisual = create_asvisual(nullptr, 0, 0, nullptr); - fgVisual->dpy = (Display*)1; //fake (not used) #endif + if (!fgVisual) { + // create dummy fgVisual for batch mode + fgVisual = create_asvisual(nullptr, 0, 0, nullptr); + fgVisual->dpy = nullptr; // fake (not used) + fgBatch = true; + } + return kTRUE; } +//////////////////////////////////////////////////////////////////////////////// +/// Static function to initialize the image. +Bool_t TASImage::InitImage(const char *caller) +{ + if (!InitVisual()) { + Warning(caller, "Visual not initiated"); + return false; + } + + if (!fImage) { + Warning(caller, "no image"); + return false; + } + + if (!fImage->alt.argb32) { + BeginPaint(); + } + + if (!fImage->alt.argb32) { + Warning(caller, "Failed to get argb32 pixel array"); + return false; + } + return true; +} + //////////////////////////////////////////////////////////////////////////////// /// Start palette editor. @@ -2609,8 +2623,7 @@ void TASImage::DrawText(Int_t x, Int_t y, const char *text, Int_t size, ASImage *text_im = nullptr; Bool_t ttfont = kFALSE; - if (!InitVisual()) { - Warning("DrawText", "Visual not initiated"); + if (!InitImage("DrawText")) { return; } @@ -3759,22 +3772,7 @@ UInt_t *TASImage::GetScanline(UInt_t y) void TASImage::FillRectangleInternal(UInt_t col, Int_t x, Int_t y, UInt_t width, UInt_t height) { - if (!InitVisual()) { - Warning("FillRectangle", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("FillRectangle", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("FillRectangle", "Failed to get pixel array"); + if (!InitImage("FillRectangleInternal")) { return; } @@ -3837,7 +3835,7 @@ void TASImage::FillRectangleInternal(UInt_t col, Int_t x, Int_t y, UInt_t width, void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height) { if (!InitVisual()) { - Warning("Fill", "Visual not initiated"); + Warning("FillRectangle", "Visual not initiated"); return; } @@ -3862,6 +3860,10 @@ void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UI void TASImage::DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick) { + if (!InitImage("DrawVLine")) { + return; + } + ARGB32 color = (ARGB32)col; UInt_t half = 0; @@ -3897,6 +3899,10 @@ void TASImage::DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thic void TASImage::DrawHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t col, UInt_t thick) { + if (!InitImage("DrawHLine")) { + return; + } + ARGB32 color = (ARGB32)col; UInt_t half = 0; @@ -3952,22 +3958,7 @@ void TASImage::DrawLineInternal(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, int idx; int yy; - if (!InitVisual()) { - Warning("DrawLine", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("DrawLine", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("DrawLine", "Failed to get pixel array"); + if (!InitImage("DrawLineInternal")) { return; } @@ -4123,7 +4114,7 @@ void TASImage::DrawRectangle(UInt_t x, UInt_t y, UInt_t w, UInt_t h, } if (!fImage->alt.argb32) { - Warning("DrawRectangle", "Failed to get pixel array"); + Warning("DrawRectangle", "Failed to get argb32 pixel array"); return; } @@ -4192,6 +4183,10 @@ void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col, void TASImage::DrawDashHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick) { + if (!InitImage("DrawDashHLine")) { + return; + } + UInt_t iDash = 0; // index of current dash int i = 0; @@ -4246,6 +4241,9 @@ void TASImage::DrawDashHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t nDash, void TASImage::DrawDashVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick) { + if (!InitImage("DrawDashVLine")) { + return; + } UInt_t iDash = 0; // index of current dash int i = 0; @@ -4303,6 +4301,9 @@ void TASImage::DrawDashVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t nDash, void TASImage::DrawDashZLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *tDash, UInt_t color) { + if (!InitImage("DrawDashZLine")) { + return; + } int dx, dy, d; int i, i1, i2; int x, y, xend, yend; @@ -4487,6 +4488,9 @@ void TASImage::DrawDashZLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, void TASImage::DrawDashZTLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *tDash, UInt_t color, UInt_t thick) { + if (!InitImage("DrawDashZTLine")) { + return; + } int dx, dy; int i; double x, y, xend=0, yend=0, x0, y0; @@ -4646,22 +4650,7 @@ void TASImage::DrawDashLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t const char *pDash, const char *col, UInt_t thick) { - if (!InitVisual()) { - Warning("DrawDashLine", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("DrawDashLine", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("DrawDashLine", "Failed to get pixel array"); + if (!InitImage("DrawDashLine")) { return; } @@ -4713,22 +4702,7 @@ void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy, const char *col, UInt_t thick void TASImage::PutPixel(Int_t x, Int_t y, const char *col) { - if (!InitVisual()) { - Warning("PutPixel", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("PutPixel", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("PutPixel", "Failed to get pixel array"); + if (!InitImage("PutPixel")) { return; } @@ -4748,22 +4722,7 @@ void TASImage::PutPixel(Int_t x, Int_t y, const char *col) void TASImage::PolyPoint(UInt_t npt, TPoint *ppt, const char *col, TImage::ECoordMode mode) { - if (!InitVisual()) { - Warning("PolyPoint", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("PolyPoint", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("PolyPoint", "Failed to get pixel array"); + if (!InitImage("PolyPoint")) { return; } @@ -4832,22 +4791,7 @@ void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg, const char *col, UInt_t void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col, const char *stipple, UInt_t w, UInt_t h) { - if (!InitVisual()) { - Warning("FillSpans", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("FillSpans", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("FillSpans", "Failed to get pixel array"); + if (!InitImage("FillSpans")) { return; } @@ -4890,22 +4834,7 @@ void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *co void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile) { - if (!InitVisual()) { - Warning("FillSpans", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("FillSpans", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("FillSpans", "Failed to get pixel array"); + if (!InitImage("FillSpans")) { return; } @@ -4944,22 +4873,7 @@ void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile) void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths) { - if (!InitVisual()) { - Warning("CropSpans", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("CropSpans", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("CropSpans", "Failed to get pixel array"); + if (!InitImage("CropSpans")) { return; } @@ -5249,22 +5163,7 @@ Bool_t TASImage::GetPolygonSpans(UInt_t npt, TPoint *ppt, UInt_t *nspans, *nspans = 0; - if (!InitVisual()) { - Warning("GetPolygonSpans", "Visual not initiated"); - return kFALSE; - } - - if (!fImage) { - Warning("GetPolygonSpans", "no image"); - return kFALSE; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("GetPolygonSpans", "Failed to get pixel array"); + if (!InitImage("GetPolygonSpans")) { return kFALSE; } @@ -5451,22 +5350,7 @@ static const UInt_t NUMPTSTOBUFFER = 512; void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col, const char *stipple, UInt_t w, UInt_t h) { - if (!InitVisual()) { - Warning("DrawFillArea", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("DrawFillArea", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("DrawFillArea", "Failed to get pixel array"); + if (!InitImage("DrawFillArea")) { return; } @@ -5567,22 +5451,7 @@ void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col, void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile) { - if (!InitVisual()) { - Warning("DrawFillArea", "Visual not initiated"); - return; - } - - if (!fImage) { - Warning("DrawFillArea", "no image"); - return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); - } - - if (!fImage->alt.argb32) { - Warning("DrawFillArea", "Failed to get pixel array"); + if (!InitImage("DrawFillArea")) { return; } @@ -5691,6 +5560,9 @@ static CARD32 gBrushCache[kBrushCacheSize*kBrushCacheSize]; void TASImage::DrawWideLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t color, UInt_t thick) { + if (!InitImage("DrawWideLine")) { + return; + } Int_t sz = thick*thick; CARD32 *matrix; Bool_t use_cache = thick < kBrushCacheSize; @@ -5737,6 +5609,9 @@ void TASImage::DrawWideLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by) { + if (!InitImage("DrawGlyph")) { + return; + } static UInt_t col[5]; Int_t x, y, yy, y0, xx; Bool_t has_alpha = (color & 0xff000000) != 0xff000000; @@ -5836,16 +5711,10 @@ void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by) void TASImage::DrawText(TText *text, Int_t x, Int_t y) { if (!text) return; - if (!fImage) return; - if (!gPad) return; - - if (!InitVisual()) { - Warning("DrawText", "Visual not initiated"); + if (!gPad) + return; + if (!InitImage("DrawText")) { return; - } - - if (!fImage->alt.argb32) { - BeginPaint(); } if (!TTF::IsInitialized()) TTF::Init(); @@ -6119,10 +5988,12 @@ void TASImage::CreateThumbnail() const int sz = 64; if (!fImage) { + Warning("CreateThumbnail", "No image"); return; } if (!InitVisual()) { + Warning("CreateThumbnail", "Visual not initiated"); return; } @@ -6343,6 +6214,9 @@ void TASImage::SetTitle(const char *title) void TASImage::DrawCubeBezier(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t x3, Int_t y3, const char *col, UInt_t thick) { + if (!InitImage("DrawCubeBezier")) { + return; + } Int_t sz = thick*thick; CARD32 *matrix; Bool_t use_cache = thick < kBrushCacheSize; @@ -6382,6 +6256,9 @@ void TASImage::DrawCubeBezier(Int_t x1, Int_t y1, Int_t x2, Int_t y2, void TASImage::DrawStraightEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, const char *col, Int_t thick) { + if (!InitImage("DrawStraightEllips")) { + return; + } thick = !thick ? 1 : thick; Int_t sz = thick*thick; CARD32 *matrix; @@ -6421,6 +6298,10 @@ void TASImage::DrawStraightEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thick) { + if (!InitImage("DrawCircle")) { + return; + } + thick = !thick ? 1 : thick; Int_t sz = thick*thick; CARD32 *matrix; @@ -6462,6 +6343,9 @@ void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thic void TASImage::DrawEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, const char *col, Int_t thick) { + if (!InitImage("DrawEllips")) { + return; + } thick = !thick ? 1 : thick; Int_t sz = thick*thick; CARD32 *matrix; @@ -6502,6 +6386,9 @@ void TASImage::DrawEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, void TASImage::DrawEllips2(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, const char *col, Int_t thick) { + if (!InitImage("DrawEllips2")) { + return; + } thick = !thick ? 1 : thick; Int_t sz = thick*thick; CARD32 *matrix; @@ -6855,4 +6742,3 @@ Int_t TASImage::Idx(Int_t idx) // The size of arrays like fImage->alt.argb32 is fImage->width*fImage->height return TMath::Min(idx,(Int_t)(fImage->width*fImage->height)); } - diff --git a/graf2d/asimage/src/TASPaletteEditor.cxx b/graf2d/asimage/src/TASPaletteEditor.cxx index 200d340075a2a..0ea09d1d6ce67 100644 --- a/graf2d/asimage/src/TASPaletteEditor.cxx +++ b/graf2d/asimage/src/TASPaletteEditor.cxx @@ -45,8 +45,8 @@ It is called by a pull down menu item of TASImage. #ifndef WIN32 # include #else -# include -# include +# define X_DISPLAY_MISSING 1 +# include #endif # include extern "C" { diff --git a/graf2d/asimage/src/TASPluginGS.cxx b/graf2d/asimage/src/TASPluginGS.cxx index 6b38db99c0dad..1a5b976d46e0c 100644 --- a/graf2d/asimage/src/TASPluginGS.cxx +++ b/graf2d/asimage/src/TASPluginGS.cxx @@ -33,9 +33,8 @@ Allows to read PS/EPS/PDF files via GhostScript #ifndef WIN32 # include #else -# include -# include # define X_DISPLAY_MISSING 1 +# include #endif # include diff --git a/graf2d/asimage/src/libAfterImage/.cvsignore b/graf2d/asimage/src/libAfterImage/.cvsignore deleted file mode 100644 index 3145fbd0709c0..0000000000000 --- a/graf2d/asimage/src/libAfterImage/.cvsignore +++ /dev/null @@ -1,8 +0,0 @@ -config.h -config.log -config.cache -Makefile -config.status -afterbase.h -afterimage-libs -.cvsignore diff --git a/graf2d/asimage/src/libAfterImage/.depend b/graf2d/asimage/src/libAfterImage/.depend deleted file mode 100644 index 16473cae3f413..0000000000000 --- a/graf2d/asimage/src/libAfterImage/.depend +++ /dev/null @@ -1,131 +0,0 @@ -./asimage.o : \ - win32/config.h \ - config.h \ - asvisual.h \ - blender.h \ - asimage.h \ - ascmap.h - -./ascmap.o : \ - win32/config.h \ - config.h \ - asimage.h \ - import.h \ - export.h \ - imencdec.h \ - ascmap.h - -./asfont.o : \ - win32/config.h \ - config.h \ - asfont.h \ - asimage.h \ - asvisual.h - -./asstorage.o : \ - win32/config.h \ - config.h \ - asstorage.h \ - afterimage.h - -./asvisual.o : \ - win32/config.h \ - config.h \ - asvisual.h - -./blender.o : \ - win32/config.h \ - config.h \ - asvisual.h \ - blender.h - -./bmp.o : \ - asimage.h \ - imencdec.h \ - bmp.h - -./char2uni.o : \ - win32/config.h \ - config.h \ - char2uni.h - -./draw.o : \ - win32/config.h \ - config.h \ - asvisual.h \ - asimage.h \ - draw.h \ - afterimage.h - -./export.o : \ - win32/config.h \ - config.h \ - asimage.h \ - imencdec.h \ - xcf.h \ - xpm.h \ - ungif.h \ - import.h \ - export.h \ - ascmap.h \ - bmp.h - -./imencdec.o : \ - win32/config.h \ - config.h \ - asvisual.h \ - blender.h \ - asimage.h \ - imencdec.h - -./import.o : \ - win32/config.h \ - config.h \ - asimage.h \ - imencdec.h \ - bmp.h \ - ximage.h \ - xcf.h \ - xpm.h \ - ungif.h \ - import.h \ - transform.h - - -./transform.o : \ - win32/config.h \ - config.h \ - asvisual.h \ - blender.h \ - asimage.h \ - imencdec.h \ - transform.h - -./ungif.o : \ - win32/config.h \ - config.h \ - asimage.h \ - ascmap.h \ - ungif.h - -./xcf.o : \ - win32/config.h \ - config.h \ - asimage.h \ - xcf.h - -./ximage.o : \ - win32/config.h \ - config.h \ - asvisual.h \ - blender.h \ - asimage.h \ - imencdec.h \ - ximage.h - -./xpm.o : \ - win32/config.h \ - config.h \ - asimage.h \ - ascmap.h \ - xpm.h diff --git a/graf2d/asimage/src/libAfterImage/.shared b/graf2d/asimage/src/libAfterImage/.shared deleted file mode 100644 index 110a949d8ecd4..0000000000000 --- a/graf2d/asimage/src/libAfterImage/.shared +++ /dev/null @@ -1,44 +0,0 @@ -LIBAFTERIMAGE_OBJS = \ - $(LIBAFTERIMAGE_PATH)/asimage.c \ - $(LIBAFTERIMAGE_PATH)/ascmap.c \ - $(LIBAFTERIMAGE_PATH)/asfont.c \ - $(LIBAFTERIMAGE_PATH)/afterrootpngwrite.c \ - $(LIBAFTERIMAGE_PATH)/asstorage.c \ - $(LIBAFTERIMAGE_PATH)/asvisual.c \ - $(LIBAFTERIMAGE_PATH)/blender.c \ - $(LIBAFTERIMAGE_PATH)/bmp.c \ - $(LIBAFTERIMAGE_PATH)/char2uni.c \ - $(LIBAFTERIMAGE_PATH)/draw.c \ - $(LIBAFTERIMAGE_PATH)/export.c \ - $(LIBAFTERIMAGE_PATH)/imencdec.c \ - $(LIBAFTERIMAGE_PATH)/import.c \ - $(LIBAFTERIMAGE_PATH)/transform.c \ - $(LIBAFTERIMAGE_PATH)/ungif.c \ - $(LIBAFTERIMAGE_PATH)/xcf.c \ - $(LIBAFTERIMAGE_PATH)/ximage.c \ - $(LIBAFTERIMAGE_PATH)/xpm.c - -LIBAFTERIMAGE_INCS = \ - $(LIBAFTERIMAGE_PATH)/afterimage.h \ - $(LIBAFTERIMAGE_PATH)/config.h \ - $(LIBAFTERIMAGE_PATH)/afterbase.h \ - $(LIBAFTERIMAGE_PATH)/ascmap.h \ - $(LIBAFTERIMAGE_PATH)/asfont.h \ - $(LIBAFTERIMAGE_PATH)/afterrootpngwrite.h \ - $(LIBAFTERIMAGE_PATH)/asim_afterbase.h \ - $(LIBAFTERIMAGE_PATH)/asimage.h \ - $(LIBAFTERIMAGE_PATH)/asstorage.h \ - $(LIBAFTERIMAGE_PATH)/asvisual.h \ - $(LIBAFTERIMAGE_PATH)/blender.h \ - $(LIBAFTERIMAGE_PATH)/bmp.h \ - $(LIBAFTERIMAGE_PATH)/char2uni.h \ - $(LIBAFTERIMAGE_PATH)/draw.h \ - $(LIBAFTERIMAGE_PATH)/export.h \ - $(LIBAFTERIMAGE_PATH)/imencdec.h \ - $(LIBAFTERIMAGE_PATH)/import.h \ - $(LIBAFTERIMAGE_PATH)/transform.h \ - $(LIBAFTERIMAGE_PATH)/ungif.h \ - $(LIBAFTERIMAGE_PATH)/xcf.h \ - $(LIBAFTERIMAGE_PATH)/ximage.h \ - $(LIBAFTERIMAGE_PATH)/xpm.h \ - $(LIBAFTERIMAGE_PATH)/xwrap.h diff --git a/graf2d/asimage/src/libAfterImage/CMakeLists.txt b/graf2d/asimage/src/libAfterImage/CMakeLists.txt index 34ed6093dfc22..44a19f2569358 100644 --- a/graf2d/asimage/src/libAfterImage/CMakeLists.txt +++ b/graf2d/asimage/src/libAfterImage/CMakeLists.txt @@ -1,55 +1,148 @@ -# libAferImage CMakeLists.txt +# Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. -PROJECT(AFTERIMAGE) -if(WIN32) - # required for the following feature & bug fix: - # 3.15: Added $ generator expression - # 3.16: Bug fix with CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS: the auto-generated exports - # are now updated only when the object files providing the symbols are updated - cmake_minimum_required(VERSION 3.16 FATAL_ERROR) - # Set CMP0091 (MSVC runtime library flags are selected by an abstraction) to OLD - # to keep the old way of selecting the runtime library with the -MD/-MDd compiler flag - cmake_policy(SET CMP0091 OLD) -else() - cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -endif() +project(AfterImage) -SET(LIB_NAME libAfterImage) +set(LIB_NAME libAfterImage) -# Microsoft Visual Studio: -IF(MSVC) - # Define - ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /DNO_DEBUG_OUTPUT /D_MBCS /D_LIB /wd4996 /wd4267 /wd4018 /wd4244") -ENDIF() +set(H_FILES + afterbase.h + afterrootpngwrite.h + asfont.h + asimage.h + asvisual.h + bmp.h + colornames.h + export.h + import.h + transform.h + xcf.h + xpm.h + afterimage.h + ascmap.h + asim_afterbase.h + asstorage.h + blender.h + char2uni.h + draw.h + imencdec.h + scanline.h + ungif.h + ximage.h + xwrap.h) -set(FREETYPE_INCLUDE_DIR "" CACHE PATH "Path to Freetype include dir") -set(ZLIB_INCLUDE_DIR "" CACHE PATH "Path to zlib include dir") +set(SRC_FILES + afterbase.c + ascmap.c + asfont.c + asimage.c + asstorage.c + asvisual.c + blender.c + bmp.c + char2uni.c + export.c + import.c + transform.c + ungif.c + xcf.c + ximage.c + xpm.c + draw.c + imencdec.c + scanline.c + afterrootpngwrite.c) -if(NOT EXISTS "${FREETYPE_INCLUDE_DIR}/ft2build.h") - message(SEND_ERROR "Can't find ft2build.h in ${FREETYPE_INCLUDE_DIR}") -endif() +add_library(${LIB_NAME} STATIC ${H_FILES} ${SRC_FILES}) +set_property(TARGET ${LIB_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) -if(NOT EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h") - message(SEND_ERROR "Can't find zlib.h in ${ZLIB_INCLUDE_DIR}") +# ASEXTRA_LIBRARIES: PNG::PNG JPEG::JPEG GIF::GIF + +target_include_directories(${LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(${LIB_NAME} PRIVATE ${ASEXTRA_LIBRARIES} Freetype::Freetype ZLIB::ZLIB) +if(TARGET X11::X11) + target_link_libraries(${LIB_NAME} PRIVATE X11::X11) endif() -INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${GIF_INCLUDE_DIR}) +include(CheckIncludeFiles) -set (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") +target_compile_definitions( + ${LIB_NAME} + PRIVATE HAVE_ERRNO_H + HAVE_FREETYPE + HAVE_FREETYPE_FREETYPE + HAVE_FT2BUILD_H + HAVE_INTTYPES_H + HAVE_MEMORY_H + HAVE_PROTOTYPES + HAVE_STDARG_H + HAVE_STDDEF_H + HAVE_STRING_H + HAVE_SYS_STAT_H + HAVE_SYS_TYPES_H + HAVE_SYS_WAIT_H + HAVE_XPM + HAVE_ZLIB_H + NO_DEBUG_OUTPUT) -FILE(GLOB H_FILES "*.h") +check_include_files(malloc.h PROJECT_HAVE_MALLOC) +if (PROJECT_HAVE_MALLOC) + target_compile_definitions( + ${LIB_NAME} + PRIVATE HAVE_MALLOC_H) +endif() -SET(SRC_FILES - afterbase.c ascmap.c asfont.c - asimage.c asstorage.c asvisual.c blender.c bmp.c char2uni.c - export.c import.c transform.c ungif.c xcf.c ximage.c xpm.c draw.c - imencdec.c scanline.c - afterrootpngwrite.c -) +if(TARGET JPEG::JPEG) + target_compile_definitions(${LIB_NAME} PRIVATE HAVE_JPEG) +endif() +if(TARGET PNG::PNG) + target_compile_definitions(${LIB_NAME} PRIVATE HAVE_PNG) +endif() +if(TARGET GIF::GIF) + target_compile_definitions(${LIB_NAME} PRIVATE HAVE_GIF) # +endif() +if(TARGET TIFF::TIFF) + target_compile_definitions(${LIB_NAME} PRIVATE HAVE_TIFF) # asimage_tiff +endif() -ADD_LIBRARY(${LIB_NAME} STATIC ${H_FILES} ${SRC_FILES}) +if(WIN32) + # Microsoft Visual Studio: + if(MSVC) + # Define + target_compile_definitions(${LIB_NAME} PRIVATE _CRT_SECURE_NO_DEPRECATE + _MBCS _LIB) + target_compile_options(${LIB_NAME} PRIVATE /wd4996 /wd4267 /wd4018 /wd4244) -target_link_libraries(${LIB_NAME} PRIVATE ${JPEG_LIBRARY_LOCATION} ${PNG_LIBRARY_LOCATION} ${GIF_LIBRARY_LOCATION}) + endif() + target_compile_definitions( + ${LIB_NAME} + PRIVATE NO_DOUBLE_FCLOSE_AFTER_FDOPEN X_DISPLAY_MISSING + HAVE_UNSIGNED_CHAR HAVE_UNSIGNED_SHORT HAVE_BOOLEAN) +else() + target_compile_definitions( + ${LIB_NAME} + PRIVATE HAVE_SYS_TIME_H + HAVE_DIRENT_H + HAVE_LONG_LONG + HAVE_STDINT_H + HAVE_STDLIB_H + HAVE_UNISTD_H + HAVE_STRINGS_H + SHAPE + STDC_HEADERS + TIME_WITH_SYS_TIME) + check_include_files(mmintrin.h PROJECT_HAVE_SSE2_INTRINSICS) + if (PROJECT_HAVE_SSE2_INTRINSICS) + target_compile_definitions( + ${LIB_NAME} + PRIVATE HAVE_MMX) + endif() + if(NOT TARGET X11::X11) + target_compile_definitions( + ${LIB_NAME} PRIVATE X_DISPLAY_MISSING) + endif() -install(TARGETS ${LIB_NAME} DESTINATION ${LIB_DESTINATION}) +endif() diff --git a/graf2d/asimage/src/libAfterImage/ChangeLog b/graf2d/asimage/src/libAfterImage/ChangeLog deleted file mode 100644 index feb43bab7b913..0000000000000 --- a/graf2d/asimage/src/libAfterImage/ChangeLog +++ /dev/null @@ -1,3797 +0,0 @@ - -2011-01-13 sasha - - * Changed version to 2.2.11 and fixed build to compile ASWallpaper - -2010-09-23 sasha - - * fixed memory leak in xcf file loading - * fixed memory leak in tga image loading - * fixed minor memory leak in gif saving code. - * fixed memory leak in xml processing on image loading - * fixed major memory leak at vectorize_asimage - * Fixed BMP writing to not set compression to 1 - we don't use any - -2010-09-15 sasha - - * fixed possible dereferencing of NULL pointer in asimage_destroy - (minor) - -2010-09-08 sasha - - * trimmed some dead code - * fixed visual2visual_prop bug in *size usage - * fixed param hidden warnings - * corrected usage of get_xpm_string() to use proper enum value - -2010-09-03 sasha - - * Fixed possible memory leak in xpm code when image is too big - * fixed unlikely but possible (if height>width) buffer overrun bug - in gradient generation code - * Fixed unlikely but possible use of uninitialized variable in - ASImage2xpmRawBuff - -2010-05-20 sasha - - * updated to libjpeg v.8b - -2010-01-29 sasha - - * added transupp to libjpeg just in case - * upgraded built-in libjpeg to version 8 - -2009-12-11 sasha - - * fixed segfault in on look change where previous look has obsolete - font settings - -2009-11-12 sasha - - * fixed export.c to properly assign default export values using - union members - contributed by Axel Naumann - -2009-10-14 sasha - - * fixed annoying ICC warnings in mystrdup use without libAfterBase - -2009-10-13 sasha - - * minor fix in afterbase.c to correct ambiguity in evaluation order - -2009-08-25 sasha - - * fixed ascompose to build without X libs - -2009-05-04 sasha - - * updated ChangeLog for the release - * AfterStep release v 2.2.9 - -2009-03-18 sasha - - * added ifdef to avoid double fclose under MSVC2005 and newer - -2009-02-11 sasha - - * Got rid of dpy global variable in libAfterBase and libAfterIMage - for good. Moved it into libAfterStep instead, as it incorporates - screen handling functionality. - -2009-01-30 sasha - - * fixed warning in jpeg2ASImage - -2009-01-16 sasha - - * fix to fill_hline_colored to work on scratch canvas + some - debugging of reported fill bugs on 64bit systems - -2009-01-13 sasha - - * fixed aliasing for drawing with brush wider then 1x1; Fixed areas - of low intensity inside solid lines - * fixed clipping in straight ellips drawing where y+ry > height - * added missing declaration of Bool asim_set_custom_brush_colored() - -2009-01-12 sasha - - * somewhat fixed drawing with ARGB brush over ARGB canvas; Still - unclear what would happen if those are different ; - -2008-12-17 sasha - - * fixed memory leak in ASImage2gif file needed to be closed even - after Egif closes it too - * fixed Makefile to work on FBSD/Gentoo - -2008-11-12 sasha - - * fixed references to the global variable dpy in GLX code - -2008-09-30 sasha - - * [no log message] - -2008-08-15 sasha - - * added utility to check if glyphs are available in the font for a - certain char or a list of chars - -2008-06-24 sasha - - * [no log message] - * Fixed root pixmap setting - to handle XKillClient failures and - not free pixmap after it was put on the root - -2008-06-23 sasha - - * [no log message] - -2008-06-18 sasha - - * [no log message] - * Updated ChangeLog for libAfterImage 1.18 release - * libAfterImage 1.18 release - -2008-06-13 sasha - - * implemented EdgeResistanceToDragging setting - -2008-06-10 sasha - - * compile bugs without X fixed - -2008-06-02 sasha - - * added missing scanline.h - -2008-05-30 sasha - - * additional logic to avoid red/blue artifacts - -2008-05-29 sasha - - * implemented some 12-bps raw image processing- demosaicing - -2008-05-02 sasha - - * [no log message] - -2008-04-23 sasha - - * Fixed build on non-gcc compilers - -2008-04-17 sasha - - * preliminary support for loading RAW camera photos stored as tiff - images with CFA data - still need to implement interpolation, - white balance, and leveling - * compile warning on signed/unsigfned comparison - -2008-04-10 sasha - - * fixed alpha overflow in color2alpha - -2008-04-07 sasha - - * implemented color2alpha method from GIMP without color correction - that was damaging the image. Complete with color2alpha xml tag - -2008-04-03 sasha - - * implemented pixelization filter - -2008-03-24 sasha - - * fixed bunch of compilation bugs showing up on old systems - -2008-03-17 sasha - - * hopefully fixed syslimit.h warnings on FBSD - -2008-03-07 sasha - - * [no log message] - -2008-03-06 sasha - - * fixed problem with docs having spaces in filenames - -2008-03-05 sasha - - * disabled build for Sound2 for now - -2008-03-04 sasha - - * fixed segfault in xcf code where layer is larger then image - * updated NEW and ChangeLogs for release 2.2.8 - * AfterStep release v. 2.2.8 - -2008-02-29 sasha - - * some more brainstorming as related to aftershow design - -2008-02-26 sasha - - * updated afterbase.c to include new stuff from libAfterBase for - xml - -2008-02-22 sasha - - * [no log message] - -2008-02-19 sasha - - * xml manipulation code added - -2008-02-18 sasha - - * [no log message] - -2008-02-16 sasha - - * started implementing aftershow client to be used by shell scripts - to redirect stdio to aftershow - * fixed asfont get_glyph_map to not confuse compilers into thinking - that there might be uninitialized stuff - -2008-02-15 sasha - - * added code to handle client connections and input to aftershow - * updated libAfterImage.mak - -2008-02-14 sasha - - * added socket setup code - need to move socket.c in here in case - afterbase is unavailable - * more X initialization code for aftershow - -2008-02-13 sasha - - * [no log message] - -2008-02-08 sasha - - * started implementing aftershow daemon - * started work on aftershow daemon - * fixed memory leak in ascompose processing in interactive mode - * compile warning on solaris in pixmap.c - -2008-02-07 sasha - - * fixed compile warning with gcc 4.3 - -2008-02-06 sasha - - * fixed compile warnings in asfont.c in win32 - * removed old png files from project - * fixed png.h to properly include zlib.h on windows and undeffed - stdint.h on win32 - -2008-02-01 sasha - - * fixed makefile to not reference obsolete libong files - -2008-01-25 sasha - - * added functionality to ascompose to allow for constantly updating - display of stuff; command line should be: script.sh | ascompose - -I --endless --click-timeout 0 -q -f -; - -2008-01-18 sasha - - * implemented full color drawing in draw.c using prototypes from - ROOT by Valeri Onuchin. Needs testing and and changes to - aply_context() - * changed draw.c to use 32bit values in canvas, possibly to enable - rendering in all 4 channels in future - need more work - -2008-01-17 sasha - - * fixed handling of grayscale PNG images with bit depth < 8 - -2008-01-16 sasha - - * partially fixed segfault on loading grayscale PNG images - * fixed segfault on loading grayscale PNG images - * enabled debugging for bigendian tests - -2008-01-15 sasha - - * moved HAVE_XPM to after config.h in libAI xpm.c; updated main - configure - * exclude xpm.c from built when no xpm is requested; no longer - support standard libgif and libxpm - -2008-01-09 sasha - - * implemented functionality to setup slicing of frame sides and - titlebar elements - * added code to kill Esetroot client if desktop background was set - by it - -2008-01-08 sasha - - * added functionality to ascompose to set XROOTPMAP property while - changing root background - -2008-01-04 sasha - - * removed erroneous configure.h include in ascompose - -2008-01-03 born2late - - * added utf8 support according to sasha s instructions - seems to - work - -2007-12-27 sasha - - * removed config.h from installation script - * added new convinience function to convert Lead Tools like DIBs - into ASImage in one call; Fixed typo in ASImage2DIB. - * Fixed major bug that maybe causing memory corruption on any - system where malloc does not return pointer aligned on 8-byte - boundary - * sanity fix to configure - -2007-12-26 sasha - - * fixed logic to not enlarge icons in menus if target size is too - big - -2007-12-19 sasha - - * giving up on trying to figure out why asvector does not work on - Power PC - -2007-12-18 sasha - - * yet another try in resolving endiannes of the XImage encoding - -2007-12-17 sasha - - * rewrote scanline2ximage32 to properly account for offset and - hopefully fix byteordering issue - -2007-12-14 sasha - - * hopefully fixed incorrect byte order while converting XImage on - 32 bit visuals back to ASImage on big endian machines - * minor cleanups in configure script to use lowercase NO - -2007-12-05 sasha - - * updated built-in libpng to 1.2.23 - -2007-11-30 sasha - - * updated xwrap.h to be the same as in libAfterBase and fixed - compilation under newer MSVC - -2007-11-26 sasha - - * Fixed memory leak in DGifCloseFile where pointer to GifFile gets - overwritten with NULL leaving dungling memory - -2007-11-20 sasha - - * fixed memory leak in gif import code - -2007-11-16 sasha - - * fixed missing initialization of ASColormap structure in - colormap_asimage - * disabled performance output in transform.c - -2007-10-25 sasha - - * added ability to load ASXML images for set size - should use - .width and .height vars inside the image to calculate different - sizes - -2007-10-16 sasha - - * Implemented proper transfer of ASImage to OpenGL drawables using - textures and pixel ops - -2007-09-21 sasha - - * altered configure to make building of apps optional - if the dir - is present - -2007-09-18 sasha - - * removed __FUNCTION__ to fix compile on Solaris - -2007-09-17 sasha - - * fixed compile errors under MSVC - * fixed compile errors in asstorage.c under MSVC - -2007-09-15 sasha - - * fixed compile warnings on solaris in asvisual.c reported by ROOT - project - * fixed compile problem under VisualStudio .Net 2005, as reported - by Valeri Onuchin - * added functions for reading raw XPM and PNG buffers, contributed - by Valeri Onuchin of ROOT project - * added ASImage2xpmRawBuff() contributed by Valeriy Onuchin of ROOT - project - -2007-09-14 sasha - - * fixed compile bug when building with shmimage and without - libAfterBase - -2007-09-12 born2late - - * minor typos corrected - -2007-09-05 sasha - - * fixed one off error in blurring code potentialy causing a - segfault - -2007-08-23 sasha - - * updated ChangeLog for release - -2007-08-22 sasha - - * compile problem on solaris fixed; Feeble attempts at increasing - performance without any results - * compile fixes and minor optimization of the blurring code - -2007-08-20 sasha - - * AfterStep 2.2.7 release - -2007-08-02 sasha - - * fixed printing of CARD32 values on 64 bit CPUs as lX - * Fixed install targets in Makefiles to create dirs - -2007-08-01 sasha - - * Fixed install targets in Makefiles to create dirs - * fixed configure and deps checking in apps - * updated ChangeLog for libAfterImage release - * Updated embedded libPNG and Zlib to latest versions; Fixed bugs - in find_file when compiled without libAfterBase. - * libAfterImage v. 1.15 release - -2007-07-31 sasha - - * added some docs to libAfterImage - * Completed refactoring gaussian blur code. It now works both in - vertical and horizontal direction. Maximum blur radius is 128, - and its bloody fast too - * optimizations to gaussian blur and fixed mystrdup(NULL) in libAI - standalone - * fixed gaussian blur at the begining and the end; added lookup - tables for standard deviation and multiplier, prototyped vertical - pass - -2007-07-30 sasha - - * implemented integer math version of gaussian blur algorithm - * fixed blur function to not limit radius to 10 and properly - calculate gaussian distribution - -2007-07-28 sasha - - * switched timing printing off - -2007-07-27 sasha - - * some additions to asstorage attempting to improve performance in - XImage reading - unsuccessfull - -2007-07-26 sasha - - * Cleaned up libAfterImage to compile without libAfterBase and - added fiunctions to ger drawable size and window position for a - specific display - -2007-07-25 sasha - - * fixes to libAfterImage to get it compiling without libAfterBase - and to reduce valgrind complaints about uninitiolized memory - -2007-07-20 sasha - - * fixed many valgrind messages related to uninitialized memory in - libAfterImage and libAfterBase; Fixed WinTabs to take into - consideration window's gravity and frame rectangle while - determining where to unswallow the window. - * fixed image reloading to keep relevant flags - that was messing - up wharf's support for look defined folder icon. That should also - speedup repeated changes of look - * adding support in Wharf for look-specific folder pixmap - so far - only works 2 times, then stops changing - weird - -2007-07-19 sasha - - * further safeguarding agains running out of storage slots in - asstorage - -2007-07-17 sasha - - * fixed the way dumb scaling up along Y axist was screwing up - slicing of the small images. - * fixed stupid dumb bug in make_scales introduced in porevious fix - * fixed a long-standing bug with slicing images getting a vertical - stripe tovards the end. Thanks DrCurl for your Patience - * fixed a long-standing bug with slicing images geting a vertical - stripe tovards the end. Thanks DrCurl for your Patience. - -2007-07-12 sasha - - * added fixes for using proper dpy (from ASVisual structure) in - many cases - -2007-07-11 sasha - - * fixed compilation without libPNG; added ability to change default - asstorage block size - * fixed bar rendering to have proper values used for unset - hue/saturation, which eliminates one extra ASImage from being - rendered - -2007-07-10 sasha - - * fixed compilation without X in libAfterImage - * reduced modules memory usage by making fonts loading on demand, - instead of on look change - -2007-07-09 sasha - - * fixed few emory leaks (minor) - -2007-07-06 sasha - - * fixed several critical bugs in causing double free and heap - corruption, based on valgrind traces - -2007-06-22 sasha - - * Improved on location where submenus are opened, to make sure they - don't completely cover parents - -2007-06-06 jeremy - - * add alsa detection to configure - -2007-05-30 sasha - - * Fixed typo causing ttf configure parameteers being ignored - -2007-05-17 sasha - - * updated ChangeLogs for relesae - -2007-05-15 sasha - - * upgraded AS version in anticipation of release - -2007-05-11 sasha - - * made ShowHints more generic option allowing iut to be used in - other modules - started modifying WinList to make use of it - -2007-05-03 sasha - - * fixed window list publishing to use new stacking_order vector - -2007-05-02 sasha - - * minor optimization of the alpha-blending code - * added test container for mmx use - * fixed MMX usage - required _mm_empty() after each mmx intrinsics - use; Optimized window title change to not regenerate icon when - not in iconic mode - -2007-05-01 sasha - - * Implemented support for root window having different color depth - - blacxk background on 16bpp screens should go away; temorarily - disabled mmx - it seems to ruin images sometimes - * fixed color printing on 64 bit system - * replaced mmx code to use gcc intinsics - -2007-04-23 sasha - - * updated ChangeLog for 2.2.5 release - * AfterStep release v. 2.2.5 - -2007-04-20 sasha - - * implemented proper support for window groups where group leader - is an unmapped unmanaged window; Added support for window groups - to move all windows in the group to a proper desktop at the same - time; Added support for restacking window groups so that when - group leader is raised/lowered - all the members follow, but not - when one of the members does the same - -2007-02-22 sasha - - * if we don't reload menu minipixmap - we need to move it over onto - new image manager - * added feature to be able to query filetype and only reload menu - minipixmap if it is ASXML script - -2007-02-20 sasha - - * added functionality to export ASIUmage into mask MS DIB data, - contributed by Valeriy Onuchin of the ROOT project - * implemented fast thumbnailing for SVG images - * work in progress - -2007-02-16 sasha - - * different check for k!=0 added to clip_line() - * check for k!=0 added to clip_line() and small change for - compilation on Apple - -2007-02-14 sasha - - * implemented fast thumbnails loading for jpeg images; added - width/height args to the tag; changed all the picture - minipixmaps accordingly and got rid of redundand .mini jpeg files - -2006-11-17 sasha - - * Updated ChangeLog for 2.2.4 release - * AfterStep release v 2.2.4 - -2006-11-09 sasha - - * fixed clamping code in hsv conversion of greyscale colors - -2006-11-08 sasha - - * finished up SVG support implementation - -2006-11-07 sasha - - * preliminary implementation of svg support in libAI using librsvg - - may need some cleaning up to be done - * added check for librsvg to configure in preparation for support - for SVG image format - -2006-11-03 sasha - - * fixed segfault when locale is not set and added special case - handling to hsv transformation to only adjust value on greyscale - pixels - -2006-10-25 sasha - - * added code to support UTF8 in menu items and comments (using - .desktop entries) - -2006-10-19 sasha - - * fixed memory leaks in libAI on image slicing - -2006-10-12 sasha - - * fixed floating point exception gets thrown by libAI upon having - to scale image up more then 255 times its height - * Added look.Smooth and fixed segfault happening when MyStyle image - needs to be semitransparent, flipped and scaled all at the same - time - -2006-10-11 vae - - * ChangeLog revisions for 2.2.3 - * AfterStep release v 2.2.3 - -2006-10-10 sasha - - * Fixed libAI to fail when subimage does not exist in the image - file - otherwise there is no way to determine how many images are - there - * added support for reading and saving animation repeat counts in - gif images - -2006-10-02 sasha - - * updated NEW and Changelogs - -2006-09-15 sasha - - * fixed infinite loop under win32 in import.c - -2006-09-13 sasha - - * fixed reading and writing animation delay in gif images - -2006-09-11 sasha - - * added ability to obtain animation delay when reading gif images - -2006-08-29 sasha - - * added function Set to AfterStep functions to be able to change - value of xml vars; added default_src param to tag to be - able to fall back on something if none of the sourceid's is - available - -2006-08-28 sasha - - * added example to if tag docs - * added and tags handling - -2006-08-24 sasha - - * fixed GIF graphics control extention's size to be 4 bytes - that - was messing up dumb MS Photo Editor - * updated libAfterImage.mak to reflect changes in libungif - * removed includes for stdint.h - -2006-08-18 sasha - - * added asxml tag to conditionally execute stuff - * added tag to asxml to be able to set variables to evaluated - expressions in xml scripts - -2006-08-16 sasha - - * added LZ compression to builtin libungif, as patent is expired - already - -2006-08-14 sasha - - * fixed ascmap.c to not leak memory in SortedColorHash buckets - -2006-08-08 sasha - - * implemented changes to automate config parsing for modules and - also implementing support for parsing module options from look - and feel - only WinList does that for now. - -2006-07-18 sasha - - * fixed handling of the text rendering where first character has a - large negative lead, such as 'j' - -2006-05-23 sasha - - * fixed Changelog generation script and updated ChangeLogs for the - release - * AfterStep release v 2.2.2 - -2006-05-17 sasha - - * implemented automatic image reloading on colorscheme change in - Wharf - -2006-05-15 sasha - - * made libAI tolerable to negative size for image transformation - functions - not to crash - -2006-05-12 sasha - - * fixed gigantic memory leak causing background images to get lost - on desktop change - -2006-05-04 sasha - - * fixed memory leaks in xml image parsing, wm_wprotocols debugging - code, menu minipixmaps, hints and several other places - -2006-04-21 sasha - - * fixed erroneous pixmap destruction by modules for tbar props; - memory leaks in WinTabs; shaped MyStyles for WinTabs tabs; - UrgencyHint cleared handling when there is no Extended WM state - -2006-04-05 sasha - - * added ability to autoformat text inserting line breaks in order - to fit it into certain width - -2006-03-31 sasha - - * added installation into alternatives list, added Games menu under - Applications - -2006-03-24 sasha - - * cirtain fixes to bugs reported on ML - -2006-03-23 sasha - - * implemented filtering of BackgroundForeign backgrounds to include - only whats supported - -2006-03-22 allanon - - * Fixed bug causing png compression to always be zero for - save_asimage_to_file(). - -2006-03-15 sasha - - * added --have-x-support to afterimage-config to test if it was - built with X display support - -2006-03-07 vae - - * ChangeLog commit for 2.2.1 - -2006-02-28 sasha - - * added check for validity of the text (no negative size) - -2006-02-15 sasha - - * fixed all the errors reported by propriatery source analyser - -2006-01-10 sasha - - * changed titlebar props setting to use different values for - NoBevel and NoAlign being set and for when those values are unset - altogether - -2006-01-09 vae - - * ChangeLog - -2006-01-03 sasha - - * fixed bug in handling of length of UTF8 text while determining - the text size - should translate length in chars into byte length - -2005-12-18 sasha - - * fixed compile bugs - -2005-12-16 sasha - - * implemented KDE config files manipulation using xml structures; - moved xml parsing into libAfterBase - -2005-12-13 sasha - - * rewrote Makefiles abit to make output more readable. Upgraded - version to 2.2.0 - -2005-12-08 sasha - - * added built-in function SignalReloadGTKRCFile to send signal to - gtk apps to refresh rc - -2005-12-04 sasha - - * fixed icons loading for AfterStep categories. Fixed configure to - work without readline available ; some warning fixed too - -2005-11-30 sasha - - * Fixed several deps in libAfterImage which were failing to compile - without libAfterBase - -2005-11-29 sasha - - * implemented better handling of the tag - with honoring of - the alpha component of the fgcolor - -2005-11-16 sasha - - * changed clipping attr in scale tag to src_ to avod collision with - tag attributes - -2005-11-15 sasha - - * fixed SIGFPE in scale_asimage2 on clip_width and clip_height - being 0 - -2005-11-14 sasha - - * added clip_x, clip_y, clip_width and clip_height to scale tag - * added ability to scale the middle of the sliced image - use - scale=1 in the slice tag - still need to add this to MyStyles - -2005-11-04 sasha - - * more file browser stuff - -2005-11-01 sasha - - * implemented faster dir scanning for image list; added time and - size to be displayed on file list; added 3 new members to TermDef - data struicture for future simplier config parsing - -2005-10-18 sasha - - * changed TTF font renderer to use advance.x attribute of the glyph - as the step instead of old way of width + bitmap_left - * implemented horizontal font kerning support for TTF fonts. Most - font's don't have that info in them though - -2005-10-05 sasha - - * fixed potential segfault in gradient parsing where number of - offsets is greater the colors - -2005-09-22 sasha - - * debugging NET_WM_ICON support - mostly works - -2005-09-21 sasha - - * implemented support for 32bit ARGB icons supplied by an app in - _NET_WM_ICON property - -2005-09-19 sasha - - * changed parsing of xml to match docs and use x_start - instead of start_x etc. - -2005-07-19 vae - - * AfterStep Release v 2.1.2 Changelog - * AfterStep Release v 2.1.2 - -2005-06-30 sasha - - * completed implementing Make XML wizard with both minipixmaps and - main wallpaper xml generation - -2005-06-26 fabs - - * removed redundant ";" to allow compilation on FreeBSD 4x - -2005-06-21 sasha - - * improved layout of XML editor - -2005-06-20 sasha - - * began implementing xml editor widget for ASWallpaper - don't - really save anythging yet - -2005-06-15 sasha - - * Implemented safer detection of AfterStep XML image type to - differentiate from XML and HTML docs; Added more controls to - ASImageBrowser - * debugged directory listing in image browser; added new file types - for HTML and XML to stop treating them as image scripts; Added - keycombo to switch windows in WinTabs - Alt +(key to the left - from 1) - -2005-06-13 sasha - - * added widget for image directory list and image browser dialog - -2005-06-10 sasha - - * implemented GTK widget for image viewing , usefull for image - browsers - -2005-06-08 sasha - - * Applyed many fixes based on output of automated analysys tool, - provided by sdague - * updated changelog for release of libAfterImage - * libAfterImage release v.1.07 - * fixed segfault on closing of asview - -2005-06-06 vae - - * AfterStep release v 2.1.1 - * ChangeLog update for 2.1.1 - -2005-06-03 sasha - - * implemented rudimentary Targa files reading - * fixes in libAfterImage for compilation and installation without - libAfterBase - eliminated debug output, type casts, etc. - * Fixed create_visual_pixmap to work with root = None; Fixed - scale_pixmap to scale even in one direction only; Fixed configure - to set path to libAfterBase to more sensible values - -2005-06-02 sasha - - * implementing import of TGA files - -2005-05-25 sasha - - * fixed gc creation code to not create a new window each time gc - needs to be created - * fixed merge function selection code in composite tag handler - -2005-05-24 sasha - - * rewrote xml handling code and broke some stuff - -2005-05-23 sasha - - * implemented slice_asimage function as yet another method of - enlarging images where corners remain unchanged, but middle part - gets tiled - -2005-05-20 sasha - - * Fixed bug in tiling of ARGB32 data in libAI and implemented - dynamic resizing of preview in ASWallpaper - -2005-05-19 sasha - - * Improvements to enable gtk apps to interoperate with libAS - -2005-05-17 vae - - * AfterStep release v 2.1.0 - changelogs - vae - * AfterStep release v 2.1.0 - vae - -2005-05-16 sasha - - * Added prototype of the GTK based tool for selecting AfterStep - backgrounds - -2005-05-04 sasha - - * Updated ChangeLogs for 2.00.05 release - -2005-05-03 sasha - - * Fixed segfault in shared memory cleanup code; Still segfaulting - on restart in FramesList cleanup code - -2005-04-29 sasha - - * added image path to ASImageManager's search path, so that - referensed images could be found from local dir. - * changed asview.c to open display prior to the image so that - display size variables would get set properly - * added image path to ASImageManager's search path, so that - referensed images could be found from local dir. - -2005-04-26 sasha - - * fixed handling of ButtonSize setting - it was ignored - -2005-04-22 sasha - - * Fixed off-by-one bug in ASStorage causing weird artefact and - possibly segfaults, due to occupied slots being reused improperly - -2005-04-21 sasha - - * hopefully fixed Segfault when window changes name at the time of - destruction - -2005-04-11 sasha - - * fixed segfault when wrong op= to composite tag is used - -2005-04-04 sasha - - * removed inline's froom functions all exported functions in - libAfterImage - -2005-03-22 sasha - - * Updated ChangeLogs for 2.0.4 release - * made desktop cover tint to be similar to Base color from selected - colorscheme - * cleaned up stale help files; got rid of sgmltools deps; updated - .spec file; changed version number to 2.0.4 - -2005-03-21 sasha - - * fixed segfault with glx enabled - -2005-03-17 sasha - - * fixed libraries listed by libAfterImage config script to include - X libs to avoid linkage problems - * implemented dynamic linking to several global vars exported from - libAfterStep to prevent compilation and linkage errors - * hopefully cleaned up shared memory usage - -2005-03-16 sasha - - * optimization of shared memory - * some debugging of asstorage code, possibly fixing segfault - -2005-03-14 sasha - - * fixed handling of special sequences in xml source of ASDocGen+ - fixed handling of several term tags within single varlist entry - -2005-03-11 sasha - - * copied DefaultFancy.ttf to libAfterImage/apps/test.ttf to avoid - possible licensing issues. Those are the same anyways, only - DefaultFancy includes Public Domain notice - -2005-03-09 sasha - - * some memory hole plugging and leaks debugging - nothing major so - far - -2005-03-08 sasha - - * debugging memory utilization - * fixed compile warnings for Alpha's cc - * fixed few compile warnings - -2005-03-07 sasha - - * fixed problem with wharf swallowing apps that were mapped on - different desktop - -2005-03-02 sasha - - * updated ChangeLog file to 2.00.03 release - * AfterStep 2.00.03 release - -2005-03-01 sasha - - * added support for IMAGE_PATH env var to all apps in libAfterImage - enabling them to view images installed in different afterstep - directories - * some docs additions - * fixed bugs: segfault and mem corruption in ASStorage when - compressed size exceeds buffer size; Proper encoding usage in - winlist menus - for UTF8 encoded window names; Proper encoding - usage in balloons - it was using ASCII regardless; Proper font in - Pager with support for international chars instead of 5x8; - Handling of $HOME at the beginning of include statements of - .include files - -2005-02-28 sasha - - * added experimental image transfer code using OpenGL API - * more performance testing with OpenGL - * gl timing - -2005-02-25 sasha - - * added prototype of image transfer to X using GLX - to see if its - any faster - * fixed compile warning - * updated configure to exclude Save - -2005-02-23 sasha - - * implemented scratch canvas functionality in draw.c to facilitate - fill operation on some countours; Added draw.h header - -2005-02-22 sasha - - * changed ~ to //home/sasha - * added FONT_PATH and IMAGE_PATH to set of envvars put out by - AfterStep - * compilation warnings and bugs submitted by Valeriy Onuchin - -2005-01-21 sasha - - * added recovery code for malformed gifs not having zero length - block at the end of compressed data - -2005-01-20 sasha - - * updated ChangeLog for 2.00.02 release - -2005-01-18 sasha - - * fixed configure for CYGWIN to build proper lib type. Implemented - Image writing into memory buffer in PNG format - see - ASImage2PNGBuff example in asvector.c - * added ability to bundle included sumenu's items under private - user items - -2005-01-17 sasha - - * configure fix - -2005-01-14 sasha - - * changed everything to make possible libAfter* as a DLLs - Scr - substituted to a pointer and same for MyArgs - -2005-01-13 sasha - - * bunch of fixes to enable shared libs under CYGWIN - but there is - still a problem of linking apps becouse of the Scr variable - -2005-01-12 sasha - - * fixed long standing bug with AS not restarting itself properly. - Upped version to 2.00.02 in preparation to release - * fixed Makefiles and -config scripts - -2005-01-10 sasha - - * ellipses, damn it - -2005-01-07 sasha - - * ellipses - -2005-01-06 sasha - - * more bloody ellips - -2005-01-05 sasha - - * bloody ellips - -2005-01-04 sasha - - * mostly done with ellips implementation using doubles - runs - faster the approximation through beziers - -2005-01-03 sasha - - * mocking about with ellips drawing algorithm - probably should - switch to doubles instead of long longs - -2004-12-29 sasha - - * some funky stuff to try to get alternative ellips algorithm going - - doesn't work yet - -2004-12-27 sasha - - * flood fill and more circle/ellipse code - -2004-12-25 sasha - - * implemented solid fill for circles - -2004-12-23 sasha - - * completed implementation of ellips and circle primitives - -2004-12-22 sasha - - * improved cubic splines to not use recursion and implemented - circle drawing - * Implemented antialiased cubical Bezier curves drawing - * implemented anialiased line rendering - -2004-12-21 sasha - - * implemented anialiased line rendering - -2004-12-20 sasha - - * fixed afterstep-config to include extra X libs; implemented - prototype anialiased drawing code - -2004-12-17 sasha - - * added test code for drawing - * added drawing functionality - * fixed performance hog introduced by data[1] changed to data[0] in - asstorage during round of warnmings fixes - -2004-12-10 sasha - - * More compilation warnings fixed - * ttf always on under win32 and typo fix in mmx initialization code - -2004-12-09 sasha - - * added list of standard X colornames - * numerous fixes from FonsRademaker and Valeriy Onuchin - to make - it compile under win32 - -2004-12-08 sasha - - * fixed bunch of warnings for different compilers - -2004-11-30 sasha - - * AfterStep 2.00.01 release - * added a configure option --disable-data-reinstall just for MG_Tak - - it prevents image, font files from being copied over existing - ones, and prevents HTML catalogue from being generated; - -2004-11-29 sasha - - * Fixed bug in afterstep not sending proper notifications about - which window is currently focused - -2004-11-26 sasha - - * fixed memory leak at add_line_mono - -2004-11-23 sasha - - * updated version to 2.00.01 - * added comments to vectorize_asimage - -2004-11-22 sasha - - * implemented vectorize_asimage and some minor fixes to Wharf - -2004-11-19 sasha - - * Fixed tiling with negative offset - unsigned/signed conversion - problem - * Debugged conversion from alt.argb32 to other stuff, like XImage - etc. using ASImageDecoder - see example in asview.c - * Implemented ASImageDecoder support for alt.argb32 format - -2004-11-16 sasha - - * changes to accomodate new aterm code - * Fixed ascmap to not segfault under MSWin and fixed fill_asimage - to use proper width when x > 0 - reported by Valeriy Onuchin; - -2004-11-15 sasha - - * fixed shading translation into tint - * fixed some code in pixmap handling used in aterm - * changed Pager invocation in start menu to use desktop number - specifyed to configure script - -2004-11-14 born2late - - * typo corrections - -2004-11-10 sasha - - * fixes to afterimage include files to properly install and enable - other apps to use it - -2004-10-27 sasha - - * began implementing XML-RPC interface to ASConfig - -2004-10-15 sasha - - * fixed libAfterImage makefile for win32 to include asstorage.c; - fixed compilation problem and excessive debug output under - windows - -2004-10-14 sasha - - * possibly resolved problem with ASDocGen not being run when - compiled with shared libraries - -2004-10-08 sasha - - * Fixed problem in base loading where there were no sanity checks - for DesktopScale value; Fixed a bug in ASStorage where small - images < 15 pixel widths would come out broken; Implemented - partially property tree printing in ASConfig; Added ASStorage - functionality to be able to query original size of the stored - data - -2004-09-27 sasha - - * changed versions to 2.00 and 1.00 for libraries - * fixed recently intoduced bug in asstorage causing major slowness; - added some logic to prevent costly maintenance operations from - happening too often - -2004-09-24 sasha - - * fixed segfault in asstorage when diff buffer does not gets - reallocated - * fixed button ungrabbing on windows withdrawing that was causing - weird BadAccess errors in Wharf - -2004-09-23 sasha - - * implemented preloading of menu pixmaps - speeding things up - considerable; fixed segfault in asstorage - still unclear how - that could happen - may see some image corruption instead - -2004-09-22 sasha - - * some performance optimization based on gprof stats, as well as - memory leak cleanups - -2004-09-21 sasha - - * added mandatory -O3 in libAfterImage and libAfterBase improving - performance significantly; - * fixed performance hog in asstorage, as well as segfault in the - same place; Implemented shaped image rendering directly into - XImage, added menu shortcuts for Left and Right keys - -2004-09-19 sasha - - * fixed possible data loss in asstorage for the very first block - -2004-09-16 sasha - - * lots of optimizations of focus change handling in WinList and - AfterStep, shape handling optimizations in Pager and other tweaks - -2004-09-15 sasha - - * added NoBorder flag to MyFrames, improved performance and - feedback in data doc generation - -2004-09-14 sasha - - * added code to background handling, to not interrupt the animation - when desktop is switched before it completes - -2004-09-08 sasha - - * changes to feel file for better shortcuts for desktop switching; - Fixes to ASStorage to properly handle reference counting without - leaving leftovers - -2004-09-02 sasha - - * Lots of tweaks to desktop switching, initial placement handling - and move-resizing - -2004-08-30 sasha - - * updated configure scripts - -2004-08-26 sasha - - * fix to Makefile to install man pages and HTML help pages - -2004-08-25 sasha - - * more xft development - * Some changes to DeadPipe to prtevent it from reentering self - -2004-08-24 sasha - - * Implemented memory debugging for buffer underruns with - --enable-audit under win32; Found memory corruption caused by - merging image of size 0, which fixes segmentation Fault in - WinList - -2004-08-23 sasha - - * Fixed make install in libAfterImage; Added missing files to - libAfterImage's project files; Fixed segfault in afterstep when - clicking happens too fast and there is no more window by the time - function is executed - * applied patch for interlaced GIF support from Maxim Nikulin - -2004-08-20 sasha - - * new development to add interface with XRender extention for text - rendering - -2004-08-19 sasha - - * fixed potential segmentation fault in asfont.c at the time of - text rendering - -2004-08-17 sasha - - * fixed compile bug in asstorage.c - * disabled clocking of transformations and text drawing - -2004-08-16 sasha - - * Changed version number to beta5, Changed AfterStep.spec to be - updated automagically with proper version number; Updated - afterstepdoc script to select web browser from mozilla, firefox, - konq, opera, netscape - -2004-08-13 sasha - - * fixed bug in asstorage causing segfaults if block is used - completely; Improved Wharf's handling of animation - should now - be much smoother - -2004-08-12 sasha - - * fixes to docs to format properly into PHP. Fixes to AsDocGen to - have nice indexes and proper references from devel docs to user - and back - -2004-08-11 sasha - - * Implemented new generated doc installation in Makefiles, added - more libAfterImage docs, fixed formatting in asimage.h and - asfont.h - -2004-08-10 sasha - - * Fixed bug in ASStorage causing negative sizes in slots and as the - result garbadge in images - -2004-08-09 sasha - - * fixed segfault bug in transform.c if image creatrion fails - * fixed some docs generation - -2004-08-06 sasha - - * added xml source for documentation into CVS and updated Look in - libAfterConf to be same as in src/afterstep/configure.c - -2004-08-03 sasha - - * Implemented 3 new types of text: OutlineAbove, OutlineBelow, - OutlineFull that does outlining of text, also enabled alpha - tinting of the text at the time of rendering - -2004-08-02 sasha - - * added memory cleanup code to ascompose, and added missing free - calls to storage destruction code - * fixed thresholding code in asstorage needed for rectangular shape - stuff - * Improved reference counting in ASStorage to accomodate to weird - storage states where some blocks have no space left for reference - -2004-07-30 sasha - - * reimplemented image reading using new functionality of ASStorage - using bitmap stuff and grayscale images using reference counters - -2004-07-29 sasha - - * debugging the size of AS menus; added storage printing function - -2004-07-28 sasha - - * disabled debug output - * rewrote ASImage contents storing code to utilize generic - ASStorage - * added 32bit store function - -2004-07-23 sasha - - * completed implementation of ASStorage, including compression - scheme for bitmapped data - -2004-07-21 sasha - - * Completed implementing RLEDIFF compression and ; Completed - debugging of asstorage with RLE DIFF compression - -2004-07-20 sasha - - * implemented decompression - * Implemented RLE diff compression code in ASStorage - -2004-07-16 sasha - - * started implementing compression using zlib - -2004-07-14 sasha - - * completed debugging and implementing asstorage - -2004-07-13 sasha - - * Implemented and debugged storage defragmentation; Moved xml - parser enums back to .h and added missing typedefs - * Fixed guarded memory handlinbg for blocks of whole number of - pages; Debugged some of the aspects of ASStorage memory handling - - must implement defragmentation now - * changed /ML flags to /MD ( based on Bertrand Bellenot suggestion) - * accepted patch from Bertrand Bellenot (Root) for libAfterImage - under Win32; Updated MSVC project files with new files - -2004-07-12 sasha - - * debugged storage storing, started implementing fetching - * added better testing code - -2004-07-09 sasha - - * partially debugged ASStorage implementation - -2004-07-07 sasha - - * storage splitting - -2004-07-06 sasha - - * ASAStorage slot selection code added - * Continued implementation of ASStorage - * implemented test container for asstorage ala XP - -2004-07-05 sasha - - * started implemnting proper storage for ASImage data - -2004-07-03 sasha - - * Updated configure scripts; spilt image decoder/encoder from - asimage - need to rearrange to get it to order - * done most of the coding required for proper handling od static - ASImages - -2004-07-02 sasha - - * implemented crosslinking docs - -2004-07-01 sasha - - * implementing urls for keywords, intellifgent handling of the NAME - section, etc. - -2004-06-30 sasha - - * Added nested subsections, partly debugged quotations, other doc - gen tweaks - -2004-06-29 sasha - - * progress in implementing static ASImages - -2004-06-25 sasha - - * prototyped doc generation for robodoc comments - -2004-06-24 sasha - - * Disabled stripping of binaries when enable-gdb is requested - -2004-06-22 sasha - - * Implemented support for static ASImages where memory is allocated - more efficiently - -2004-06-21 sasha - - * added support for UTF-8 when its requested in LC_LANG setting - -2004-06-13 sasha - - * Introduced new type of image - static to add flexibility in - regards to memory allocation - -2004-06-10 sasha - - * added xml tag so that temporary images could be unload - to free up some memory - -2004-06-08 sasha - - * Fixed race condition with modules using LOCKONSEND and display - being grabbed - * added ability to XML parser to recognize known tags; Added - framework code for converting source xml into html docs to - ASDocGen - -2004-05-24 sasha - - * fixed scaling algorithm to properly scale images with height <= 3 - -2004-05-18 sasha - - * updated dependancies, and completed reimplementing Animate module - - still needs some debugging though - * fixed erroneous uncommented line in shared memory XImages - -2004-05-17 sasha - - * cleaned up C++ comments - -2004-05-13 sasha - - * debugging background changing - * hopefully fixed detection of freetype library on debian sarge - -2004-05-12 sasha - - * updated configure scripts and partly fixed freetype autodetection - for debian - still need ft2build adding to freetype.h detection - code - * implemented fast(er) desktop switching by caching background - pixmaps - there are some quirks that needs to be ironed out still - -2004-05-11 sasha - - * fishing out segfault in get_text_size - * Implemented memory debugging under cygwin and fixed discovered - bug in MyStyle parsing - -2004-05-10 sasha - - * Implemented Transient button functionality in Wharf, missing from - 1.8 - -2004-05-07 sasha - - * minor TODO changes - -2004-04-29 sasha - - * Implemented ability to use tab stops while drawing text, and - cleaned up new api calls; Fixed Wharf Bevel setting - -2004-04-19 sasha - - * Implemented ability to load any font as monospaced using scaling - of glyphs and other techniques, making it possible to use - libAfterImage for text output in applications such as text - editors and terminal emulators - -2004-04-15 sasha - - * Fixed bug in handling of Viewport setting in database when only - one of the x or y is set.It was using X set flag for y value and - wise versa - -2004-03-31 sasha - - * Fixed potential segfault in asfont.c when font is NULL; Fixed - including of afterbase.h in asapp.h to be done only when compiled - as part of AfterStep - -2004-03-19 sasha - - * added includes for xmd.h prior to jpeglib, to prevent multiple - definitions of INT32 - * added missing include for system's zlib.h in png.h - * removed unneeded io.h from libungif - -2004-03-18 sasha - - * Found and fixed very weird heap corruption bug, causing segfault - whenever bevelled rectang is drawn - * Added builtin libungif to libAfterImage, and enabled support for - it by default in configure - -2004-03-17 sasha - - * added MSVC nmake makefiles - * fixed libAfterImage to properly handle path in win32 - -2004-03-16 sasha - - * Incorporated libpng, libjpeg and zlib into libAfterImage, in case - it is not available on the target system, or we are compiling - under win32 - -2004-03-11 sasha - - * Completed implementing conversion from ASImage into DIB and - implemented sample win32 image viewer application as an example - and testbed. - -2004-03-10 sasha - - * started implementing ASImage2DIB converter - * moved some of the bmp functionality into bmp.c/h - * removed 0x0D that came from MSVC porting - * changes to make libAfterImage compile under MSVC in win32 - * began porting libAfterImage into win32 - -2004-03-05 sasha - - * Fixed compilation in Feel.c with --enable-gdb; Fixed local - selection if only the country is specified such as en_US - RedHat - seems to have this; Fixed segfault in spawn_child with locale - specified it was attempting to check if pointer is isspace() - triggering bug in glibc - -2004-03-04 sasha - - * Fixed annoying type-punning warnings; Fixed annoying -rdynamic - warnings on CYGWIN; Changed default compression ratio for - screenshots to give very high quality; Fixed configure.in to - properly work with latest autotools supporting PACKAGE_ stuff; - Fixed configure to remove -g if enable-gdb is not requested; - Fixed root image grabbing using overlay window to not use Backing - Store; Fixed ascompose to set USPosition when geometry is - requested; Fixed Banner to set its title ; Upgraded version to - beta4 - -2004-03-01 sasha - - * better Banner - * removed redundand ifdefs for I18N - * debugged and optimized Banner and ascompose - -2004-02-27 sasha - - * added missing usage text to ascompose and fixed Makefile to - install Banner - * improved ascompose - * debugged mask to rectangles list functionality in asimage.c - -2004-02-26 sasha - - * added support for shaped windows to ascompose; Debugged - channel->rectangle set conversion in libAfterImage - still have - some vertical stripes - * Fixed tag in asxml to properly swap width and height in - case of 90 or 270 degree rotation - -2004-02-21 sasha - - * added code to AfterStep to publish Image and Font path in env - vars; Added feel.ICCCM that has no keyboard bindings; Added - window centering code to ascompose; Added missing cursor - definitions to look.QNX; - -2004-02-20 sasha - - * Added ability to wait for data placed in X clipboard and then - displaying it if its in XML format - -2004-02-19 sasha - - * added ability to use same window for different images - * fixed display closing when running in loop - * added interactive error reporting functionality - * added interactivity functionality to ascompose - -2004-01-27 sasha - - * now hopefully workplace state restoration should work fine - - fixed complex function name parsing, for cases when its nested - within anopther complex function. Also added checks to not - remove -g even if --enable-gdb is not specified ( due to requests - from debian folks) - -2004-01-21 sasha - - * fixed bug where empty locale would be specified while starting a - module causing Pager to have 255 desktops and other weirdness - -2004-01-13 sasha - - * fixed bug in shared image variant of background xfer - * disabled animating for tiled pixmaps as it seems to cause - slowness - -2004-01-12 sasha - - * hopefully optimized ximage transfer by using reusable memory and - added ability to postpone background switching task to be done - later - -2004-01-08 sasha - - * fixed libAfterStep installation procedure and some of the headers - to make it useable in external apps - -2004-01-06 sasha - - * fixed get_font to not crash when X is missing; Fixed ascolor to - not open any connections to AS when -n option is used - -2004-01-02 sasha - - * Fixed keyboard presses handling to not require window selection - when there is a focused window; Updated .spec file to better - handle libraries and stuff ( thanks to Andre Costa ) - -2003-12-23 sasha - - * Fixed README.SOLARIS and libAfterImage's Makefile if's - -2003-12-17 sasha - - * added width/height value "proportional" to tag to keep - image ratio while scaling - -2003-12-09 sasha - - * got rid of Wait3 testing in configure - should speed it up a bit - -2003-12-08 sasha - - * fixed handling of trailing whitespace at the end of the tag in - XML processor - * added support for C control codes in printf format strings in - asxml, added safeguards to check for proper number of parameters - in printf format string - * fixed support for input from stdin and output onto stdout in - ascompose - -2003-12-05 sasha - - * Cleaned up configure to not have ugly -I.. -I../.. and not do any - detection of libAfterImage/Base - we should always use what we - came distributed with - * fixed without-x compile problem in asvisual.c - * fixed stddef.h bug in libAfterBase and without-x compile problem - in asimage.c - * added tag to asimage xml to enable output of internal - variables such as image size - -2003-11-28 sasha - - * added afterimage-config - -2003-11-14 sasha - - * Added cover window to meaningfully show user that AfterStep is - reloading config or starting up or doing anything else that takes - time - -2003-11-07 sasha - - * Added ActiveDeskBevel and InActiveDeskBevel to Pager's options; - Debugged bevel drawing when tbar has different bevels for focus - and unfocus states( should get rid of weird black frame when one - of the states is None) - -2003-09-25 sasha - - * AfterStep 2.00.beta2 Release - * Some minor tweaks to cursor coloring and HSV manipuylation for - grayscale - * Implemented automagic generation of the ChangeLog - -2003-09-22 sasha - - * Fixed locale parsing from LANG variable; Fixed module startup to - pass on current locae specified on command line - -2003-09-09 sasha - - * More fixing Pager's geometry; Added -i cmd line parameter to - ascompose to allow for 'include' files (such as colorschemes, - etc.); Updated configure scripts to properly detect headers when - its run from libAfterBase; Updated version to beta2; Updated TEAM - file - -2003-09-08 sasha - - * Fixed Pager to properly account for label size while sizing - min-desktop windows - -2003-09-03 sasha - - * added new AfterStep log icon; fixed wharf config file - -2003-09-02 sasha - - * added new xml tag : to define symbolic color names - -2003-08-30 sasha - - * debugged workspace state handling code, and improved Wait loop - -2003-08-28 sasha - - * added caching of pixmaps for unfocused bas in window decorations - to speed up fast focus switching - * 64-bit fixes: properties and strlen warnings - -2003-08-27 sasha - - * fixed handling of non-default MyBackgrounds, and proper adding of - DeskConfigs while switching desks - * synching - -2003-08-26 sasha - - * added parameters to import funcions, to allow for sized - image/preview stuff; Removed compression buffer from ASImage - structure to save up some memory; Hopefully fixed hints handling - on 64 bit hw - -2003-08-23 sasha - - * added new 3 icons to complete the set of default icons: switched - AfterStep to use ~/.afterstep instead of ridiculous ~/GNUstel/L/A - stuff - -2003-08-22 sasha - - * fixed autodetection of zipped xpms and added 6 more icons to - default iconset - -2003-08-21 sasha - - * more improvements to asimbrowser - -2003-08-20 sasha - - * implemented html generator for icons list (asimbrowser); TODO: - replace all asimage_decode_line with Image Output thingy, or - implement support for back_color - -2003-08-19 sasha - - * implemented image list loading from dir listing - -2003-08-18 sasha - - * configure regenerated - * changes to configure to properly handle user set LDFLAGS - * configure regenerated - * changes to configure to properly handle user set LDFLAGS - * configure regenerated - * changes to configure to properly handle user set LDFLAGS - * configure regenerated - * changes to configure to properly handle user set LDFLAGS - -2003-08-15 sasha - - * applied 5 patches from Stasinos Konstantopoulos - * updated configure scripts to autoconf 2.57 - * more messing aruound with system headers and compilation - * updated configure scripts - * more messing aruound with system headers and compilation - * updated configure scripts - * more messing aruound with system headers and compilation - * more work on compilation issues, notably fixed errors on old - debian 2.2 - -2003-08-14 sasha - - * disabled gif/ungif by default - * disabled gif/ungif by default - needs to be reenabled manually - * compilation warnings fixed - * updated configure - * hopefully fixed all the strict aliasing breakage errors with - newer gcc - -2003-08-13 sasha - - * bugfixes in Pager and Wharf, and fixed handling of malloc.h - -2003-08-12 sasha - - * removed offending varargs include that was not needed anyways, - but was breaking compile with gcc 3.3.1 - -2003-08-11 allanon - - * fail gracefully if merge is requested and no images can be loaded - -2003-08-11 sasha - - * cleanup in preparation to beta1 release - -2003-08-09 sasha - - * added cleanup code for shared memory - -2003-08-08 sasha - - * added safety check for shared memory utilization - -2003-08-07 sasha - - * fixed bug in ASImage to shape conversion causing disappearing - titlebars in glass look - -2003-08-01 sasha - - * rewrote shaped windows handling to use rectangles everywhere, and - intelligently merge them together, thus greately reducing memory - utilization and avoiding flickering and other nasty artifacts. - That's it, last commit before beta1 release :) - I'm off for - vactaion, coincedentally :) - -2003-07-23 sasha - - * added feature allowing for the menu minipixmaps to come from - files with specified extension, such as .mini - -2003-07-22 sasha - - * fixed error message while trying to load X11 font with part of - the name truncated as the result of size parsing - -2003-07-18 sasha - - * completed implementation and debugging of shared memory - extensions use in afterstep proper; Fixed compression of xml - images - save a bundle or root pixmaps - -2003-07-17 sasha - - * Fixed bug in asimage2ximage where asv->dpy was used instead of - asv; Fixed bug in Pager's handling of folders while checking - availability - * completed implementation of support for shared memory XImages - -2003-07-16 sasha - - * added look.Glass (look-alike of 23 Oz Glass E theme); Fixed - shaped windows bug in mystyle image rendering (alpha channel was - being lost); Added ability to adjust hsv of the color; fixed bug - in window decorations handling - background images - -2003-07-15 sasha - - * mostly completed wharf config - -2003-07-14 sasha - - * added icons for terms and added better availability check to - Wharf and AfterStep - Wharf now allows to choose from one of the - icons - -2003-07-13 sasha - - * fixed configure script to properly compile libAfterImage apps - -2003-07-11 sasha - - * Implemented 3 more functions: TakeScreenShot, TakeWindowShot and - TakeFrameShot, as the side effect of debugging root background - handling. Updated feel.DEFAULT to use those - * fixed bug in inheritance code where back_icon would get destroyed - even if it was inherited, thus causing weird things to happen - when same style is inherited twice; Added code to - mystyle_make_image to ensure that we always produce valid ASImage - -2003-07-01 sasha - - * fixed uninitialized ximage pointer usage in create_visual_ximage - * continued development of the xshmimages - -2003-06-30 sasha - - * fixed shmem autodetection - * added support X Shared Memory Image extensions ( mostly ) ; - -2003-06-27 sasha - - * Fixed handling of xv's crazy WM_HINTS changing and overal;l hints - changing; Fixed out of bounds memory access in make_file_name and - picture_ximage2asimage; completed support in configure for X - Shared Memory images - -2003-06-26 sasha - - * Fixed bug in libAfterImage causing garbadge in gradients 1 pixel - wide - -2003-06-25 sasha - - * Fixed transparent gradient drawing to do alphablending instead of - allanon; Fixed menu to not show underscores; Fixed menu look - update; Added feature to Wharf to verify that Exec command - commands are actually available in PATH; Fixed balloons drawing - to withdraw them as pointer leaves the window - -2003-06-23 sasha - - * made afterstep UTF-8 aware. - -2003-06-21 sasha - - * debugged UTF8 rendering with libAfterImage and Default.ttf font - -2003-06-20 sasha - - * fixed UTF8 char size calculation - * Fixed bug in unicode character drawing causing segfaults - -2003-06-09 sasha - - * Fixed compilation of libAfterImage without libAfterBase - -2003-06-06 sasha - - * Fixed gradient type handling; Fixed PinMenu in feel for button 5; - Added check for what side should be dragged when window is - resized without pressing on the frame - -2003-06-05 sasha - - * gradient rotation code implemented for vertical titlebars - * fixed manual placement so that window's corner is at the mouse - position - -2003-06-04 sasha - - * created pressed buttons for the default look; Fixed bug in - load_file where file would get opened twice - -2003-06-03 sasha - - * redesigning default titlebar buttons - * Implemented NoFocusOnMap database hint; Added opacity setting to - solid tag in xml: - -2003-06-02 sasha - - * minor fixes to xml parser - -2003-05-30 sasha - - * Added several new attributes to composite and text tags for: text - 3d type, align, vailgn ( in asxml handler ); Fixed text - foreground image handling in asimagexml; Designed new default - background as composite of gradient and old texture with text on - top of it. - -2003-05-28 sasha - - * completed debugging colorscheme tools - need to check into way of - calculating saturation and value - -2003-05-22 sasha - - * Makefile fixes to make libAfterImage and libAfterBase packageable - for RedHat - -2003-05-20 sasha - - * Implemented colorscheme parsing/writing (mostly) - -2003-05-19 sasha - - * added handling of button pressing to ascolor; Fixed bug in man - page installation for libAfterImage reported by MG_Tak - -2003-05-09 sasha - - * Fixed image storing in xml scripts using id= attribute; Added - check for minimum text color brightness when whitening it; Added - more bars to ascolor.c; Fixed bug in Makefiles for shared - libraries; - * fixed compile bugs in parse.c and completed hsv/rgb custom color - parsing - -2003-05-07 sasha - - * prototyped FLTK based ascp; Made all the libraries C++ safe - -2003-05-06 sasha - - * added csome code to produce nice colorschemes automagically - -2003-04-25 sasha - - * fixed loading of images inside xml scripts to use same PixmapPath - as everything else - * added .xpm to filenames of old buttons - * Got rid of old MyFont cruft; Got rid of global GCs in MyStyles; - Fixed handling of FontPath and loading of TTF fonts - -2003-04-22 sasha - - * added bunch of xml icons for titlebar buttons; removed fprintf - from transform.c - -2003-04-21 sasha - - * generated bunch of dots icons from buttons - -2003-04-18 sasha - - * improvements and fixes to asimagexml adding new flags to bevel - tag and fixing handling of IMAGE_PATH env var - -2003-04-16 sasha - - * updated configure script - * Fixin Makefiles for new icons etc - -2003-04-08 sasha - - * missing braces in ico import code; Fixed large icons broken by - broken libAfterImage; Added Bookshelf and Package icons - * Fixed scaling Up algorithm to put correct last line ( it was - putting 4th line before last instead); Fixed MS Icon file format - reading to allow for arbitrary size of images ( it was affecting - AndMask not being read correctly; - -2003-04-03 sasha - - * added xpm2png conversion script - -2003-03-28 sasha - - * Fixed bug where while writing bitmap mask we would forget to - unset flag indicating that it is 8 bit mask - -2003-03-26 sasha - - * Fixed segfaulting with 64bit compile due to 32bit values used - instead of pointers in calls to get_hash_item - -2003-03-25 sasha - - * some changes to make code 64-bit safe - -2003-03-21 sasha - - * fixed nasty segfault in image tracing code; addede more - descriptions to NEW; continued work on saving desk/viewport: - -2003-03-19 sasha - - * Fixed text size miscalculation due to starting counting from - second character instead of first - * implemented gaussian blurr for selected channels in ascompose:) - WE can now easily convert icons into png - -2003-03-10 sasha - - * debugged root background handling so that aterms should not crash - now; Scaled/tiled/clipped backgrounds should reload now; There - will be no multiple copies of the image kept in AS memory - anymore; - -2003-03-04 sasha - - * upgraded version, rearranged and renamed libraries to match - as-devel; updated includes in libAfterConf and libAfterStep - -2003-02-24 sasha - - * Hopefully fixed gamma correction issue in PNG images - -2003-01-07 sasha - - * IMplemented shaped windows support in as-proper; Implemented - shaped Wharf; Debugged labels in Wharf; Fixed bug in image - flipping code where color could get lost when original uses - back_color; - -2002-12-19 sasha - - * cleaned up and debugged background image handling; fixed clients - stacking order in Pager; ICCCM ConfigureNotify on frame moves - reenabled; proper config broadcasting at the time of the actuall - ConfigureNotify; stacking order gets sent on WindowList request; - -2002-12-05 sasha - - * Fixed bug in image flipping where back_color would get lost; - Implemented menu style in database as Style ASMenu; began working - on Pager and WinList2 to get them to compile and run with new - as-proper - -2002-12-04 sasha - - * sugnificantly improved speed of menu rendering as well as - loading time; - mostly implemented Pinning of the menus - need to debug - redecoration of the frame window; - -2002-12-02 sasha - - * Fixed root pixmap grabbing using ParentRelative; Fixed label - layout moving label off alittle bit; Began implementing support - for DrawMenuBorders setting - -2002-11-15 sasha - - * Fixed memory leaks in asfont.c,list.c,decor.c and InitLook(); - Implemented proper cleanup to produce clean memory leak output; - Implemented smooth shading animation in both directions - -2002-11-14 sasha - - * Fixed titlebar button contexts;Fixed decoration - focusing/unfocusing; fixed pressing/depressing; Fixed segfaults - in LookInit (pixmaps); Fixed numerous memory leaks in menu - parsing and in font loading; - -2002-11-06 sasha - - * Moved MyStyles to use Hash table, Fixed mystyle_property code to - use wmprops; updated libConfig to use asapp and fixed MyStyle - parsing; cleaned up bits and pieces and at long last got - AfterStep proper to compile cleanly cd as-stable! Now its time - for some debugging - -2002-10-30 sasha - - * making progress to get as to compile - link time errors now - -2002-10-18 sasha - - * started fixing functions.c; fixed bug in event.c reported by - tildouf - -2002-07-24 sasha - - * implemented shaped decoration drawing - see winlist2 with - BackPixmap set to 125 or 126 for any of the styles - -2002-07-23 sasha - - * Fixed afterstep proper to use same functions as mystyles for icon - loading( with shapes and alpha-channel) Fixed bugs in mystyle - text drawing; some ximage.c functions where bitmap parameter was - wrong; Changed titlebar buttoins to use MyIcon and MyButton; - Changed Frames to use MyIcon with shapes and everything; Fixed - menu to properly load and unload icons - -2002-07-22 sasha - - * completed implementation of 8-bit alpha channel pixmaps in - libAfterImage; added function to hopefully determine the most - efficient depth of alpha channel (8 or 1); added 8-bit alpha - support to icon_t and mystyles; fixed bugs in MyStyles cloning of - mask; added twm rubberband; fixed Audio (see AS ML) - -2002-07-20 sasha - - * added some functions for export of alpha channel into 8 bit - pixmap and back - -2002-07-16 sasha - - * Parameter check bugfix in marge_layers in libAfterImage; Rewrote - WinList layout, to do it two steps - -2002-06-24 allanon - - * o re-ordered a bit of code so that the width and height - attributes of - could use variables defined by children of the tag - -2002-05-24 sasha - - * compilation warning - -2002-05-22 allanon - - * o added support for multi-bit-depth displays like those found on - Solaris - boxes: 8bpp root window, with 24bpp possible to afterstep; - note that - asetroot still does not support this situation, so - transparency modes - do not work - o moved around audit.h includes to allow AS to be compiled with - --enable-audit again - -2002-05-18 sasha - - * added configure option to enable reusing loaded font by modules - (old way) - -2002-04-25 sasha - - * cleaned up headers and fixed Makefiles - -2002-04-23 sasha - - * Fixed Pager to use correct color parsing; Added ARGB2PIXEL - converters for pseudo-color modes; Removed GCs from Wharf - -2002-04-21 sasha - - * fixed Wharf to (hopefully) work with libAfterImage. Fixed several - minor bugs in libAfterImage - -2002-04-19 sasha - - * more wharf work. Added xpm_data2ASImage() - -2002-04-17 sasha - - * fixed bug in ASImage->XImage conversion where back_color was not - properly padding scanlines - -2002-04-16 sasha - - * slightly improved logic of gradient drawing to account for - completely messed up offsets - -2002-04-15 sasha - - * synced with as-devel/libAfterImage - -2002-04-13 sasha - - * Reimplemented MyStyles using libAfterImage - include ssome - changes to MyStyle data structure. Tinting now works both ways - - darkens and lightens. all 15 blending methods should work now. - half of the modules needs fixing to compile - -2002-04-09 sasha - - * Syncronized with devel tree - xml vars, stdout image export - -2002-04-03 allanon - - * Added variables to the XML image parsing. - -2002-04-03 sasha - - * Added self diag code. Fixed bug in libAfterImage where Mask was - incorrectly exported into ximage - -2002-03-28 sasha - - * fixed libAfterWidegt to get asclook to compile again - * Completed pixmap manipulation functions port from old - libafterimage - -2002-03-27 sasha - - * compile warnings - * Alpha portability fixes - * portability fixes - -2002-03-26 sasha - - * fixed lousy bug in tiling code where data was coming out - randomly - -2002-03-23 sasha - - * almost done with pixmap.c - -2002-03-19 sasha - - * implemented draw_unicode_text and draw_utf8_text and - get_text_size for those as well - * minor tweaks to asvector.c - -2002-03-17 sasha - - * Locale support for TTF fonts mostly completed - need to add - draw_text_unicode and draw_text_utf8 - -2002-03-15 sasha - - * right smack in the middle of unicode debugging, loosing bloody - glyphs somewhere :( - -2002-03-12 sasha - - * hopefully completed locale string parsing - -2002-03-11 sasha - - * adding decoder for locale names - -2002-03-10 sasha - - * Implemented large portion of locale/unicode support in text - drawing - -2002-03-09 sasha - - * completed implementing char to unicode conversion - -2002-03-08 sasha - - * added test container for vector draving - -2002-03-02 allanon - - * o fixed segfault when no valid image is generated at all - o xml_print() now indents xml so it's more readable - -2002-03-02 sasha - - * fixed missing argument in query_screen_visual macro - -2002-03-01 sasha - - * implemented 8-bit mask output into XImage and reverse mask - decoding into alpha channel from attached mask XImage - -2002-02-26 sasha - - * done with ximage tiling code, now we can use XImages instead of - encoded ARGB data - -2002-02-22 sasha - - * made possible to use XImage data directly for other - transformations - need to complete scanline tiling code and add - trigger disabling DATA_UNUSABLE flag - -2002-02-21 sasha - - * started adding decoding capabilities for ASImages that only has - XImage/ARGB data - * added colormap parameter to create_asvisual_from_id, so that - custom created colormap could be passed for libAfterImage to use - from calling app. - -2002-02-20 sasha - - * minor portability fixes - -2002-02-19 sasha - - * Added xml2ASImage input filter. Changed gradient drawing code to - not assume ascending order of offsets. - -2002-02-18 sasha - - * converted ascompose to use xml code from asimagexml.c and did - some cursory debuggin - -2002-02-16 sasha - - * completed asimagexml - now to convert ascompose to use it and do - some funky debuggin for meory corruption/leaks and other features - :) - -2002-02-12 sasha - - * mostly done with asimagexml refactoring - -2002-02-11 sasha - - * added asimagexml - input filter that allows to perform complex - transformation on image transparently for the app and based on - supplied XML file. - -2002-02-05 sasha - - * fixed vector->RGB generation to treat vector data as if it was - from bottom to top, instead - -2002-01-17 sasha - - * Fixed bug in ascompose where command line argument could be - freed. Fixed bug where wrong destruction function has been used - in image hash in ascompose. - * Fixed segfault when opening XPMs with greater then 256 colors. - Hopefully satisfied stupid gcc 3.0.3 when it stumbles upon - printf() with ifdefs inside. - -2002-01-15 sasha - - * Updated ChangeLogs - * updated docs - * updated deps and configure scripts - * Upped version number for libAfterImage and libAfterBase - -2002-01-14 sasha - - * added missing AS_HASHABLE and show_progress - * added missing show_debug into afterbase.c/.h - * Completed portability fixing of the day - * Removed unneeded debug code - * Fixed embarrasing bug in MAX macro - it really worked the same as - MIN :) *GRRRRR* - * debugging on 64bit big emdian machine - * XParseGeometry requires unsigned int* - * Added mandatory libm , since we now need exp() from gaussian - blurr - * XParseGeometry expects pointers to unsigned int - * DOS format somehow creeped in :( - * datatype portability issues - * __FUNCTION__ macro portability issues - * Hopefully bomb-proof freetype detection - * prototyped ASCommManager - for the generic even/input loop - handling - -2002-01-10 sasha - - * Updated ChnageLogs for libAfterImage and libAfterBase - * Fixed bug in bevel drawing where right solid line would not be - drawn - * added XGCValues to xwrap code - * updated libs configure script with new version and correct - help/options - * Fixed makefile to install ascompose man page into correct - location, since it is an app it should go into man1 - * updated man pages - -2002-01-09 sasha - - * Completed documenting libAfterImage's latest additions. - -2002-01-08 sasha - - * Completed documenting ascompose.c Regenerated .HTML docs - -2002-01-07 sasha - - * done with about 50% of ascompose documentation. - -2001-12-31 sasha - - * Fixed HSV and HLS colorspaces to correctly assign meaningfull HUE - values with straight mapping onto 360 degree colorcircle with red - being 0, green 120 and blue 240 degrees. Fixed - adjust_asimage_hsv to correctly translate degrees. debugged - tag in ascompose. Added ARGB32_RED16 macro and the likes. - * added HSV transformation - -2001-12-28 sasha - - * Fixed alpha handling in allanon and add methods of blender.c - Fixed minor bugs in ascompose related to clip_height handling in - composite tag. - -2001-12-27 sasha - - * greateluy improved ascompose fixed bug when colormap had 128 - entries in gif transparency - -2001-12-26 sasha - - * Added compress, replace and delay attributes to save tag in - ascompose. - -2001-12-25 sasha - - * debugged GIF and XPM transparency - -2001-12-24 sasha - - * Fixed bug in PNG with alpha writing, where alpha channel could - get lost. Fixed bug in Gif reading where extensions where lost. - Updated ascompose to use show_progress/error instead of plain - printf fixed libAfterBase to compile - -2001-12-14 sasha - - * Lots of fixes for session handling, look/feel loading and - non-default-visual handling - * Fixed visual detection code to not create new Colormap when - Default Visual is in use. - * Fixed Visual Autodetection code to correctly create windows for - visuals other then default visual. - -2001-12-12 sasha - - * Added ability to specify preferred Visual ID via env. variable - AFTERIMAGE_VISUAL_ID - -2001-12-07 sasha - - * When scale_asimage is called with quality set to POOR it will not - interpolate pixels, but merely duplicate existing ones. When - scaling down is perfomed it will it will keep averaging pixels - values nevertheless. Added tiling_range to ASImageOutput to - allow filling of portion of the image with the same scanline. - Fixed bug in enlarging algorithm causing corruption of the image - near the right edge. - -2001-12-06 sasha - - * Fixed minor compilation problems reported by Reiner Rohlfs. - * added ARGB2pixel conversion for 16/15bpp; Fixed bug where root - position of window was not updated on move - -2001-12-05 sasha - - * Fixed bugs in merge_asimage and bevel drawing causing segfaults - and wrong images when negative destination is used. - * fixed bug in merge_aslayers that was not traversing layers list - correctly - -2001-12-04 sasha - - * continued debugging of image rendering with varying dest position - in layers - -2001-12-03 sasha - - * Removed unneeded ASVisual arg from clone_asimage. - * Completed rewriting bevel rendering. It should now correctly trim - bevel when requested to do so. - -2001-11-30 sasha - - * More rendering/look debugging. Fixed Titlebuttons handling. - Started rewriting bevel drawing to enable drawing of bevel on - clipped images when some parts of the bevel maybe outside of the - clip rectangle. - -2001-11-29 sasha - - * Extensive debugging of new rendering code. - -2001-11-28 sasha - - * Implemented actiuall dubblebuffered drawing. Fixed all the - compile time bug - need to get asclook to actually draw - something. - -2001-11-25 sasha - - * Added check for correct libPNG - -2001-11-20 sasha - - * Added desktop layout to ornaments - incomplete - * ByteOrder debugging - fixed misaligned green channel in ASImage-> - XImage conversion in MSBFirst != BigEndian configuration - * ByteOrder debugging - * portability and compilation fixes - -2001-11-15 sasha - - * Debugged Vector data drawing code and added optimizations for - repetitive data. - -2001-11-14 sasha - - * Added new fixes from Fons Rademaker Implemented ASImage support - for data in vector of doubles with additional pallette to - translate into real ARGB. - * added automated check for MMX support to libAfterImage - -2001-11-02 sasha - - * Applied next batch of diffs from Fons Rademakers. Fixed several - cuel bugs in libAfterWidget, causing memory corruption. Changed - ASHashableValue to be simply unsigned long - for portability. - -2001-10-26 sasha - - * moved widget event handling into widgetevent.c/.h - * Added patches for compilation into C++ proggrams ( contributed by - Fons Rademakers) Implemented export filter into TIFF. Hopefully - fixed library order when compiling apps from libAfterImage - -2001-10-22 sasha - - * Added viewport changing functionality - -2001-10-12 sasha - - * Moved per-desktop look/feel management into session.c. Made - asclook compile and debugged libAfterImage's use of AS_ASSERT. - -2001-10-10 sasha - - * Added missing string_destroy into afterbase.c - * Added missing remove_hash_item into afterbase.c - * Fixed Makefile to work without libAfterBase - * Updated ChangeLogs - * completed update of the documentation for libAfterImage - * updated documentation and deps - * Fixed configure script to be able to compile libAfterImage and - libAfterBase at once - -2001-10-09 sasha - - * Updated most of the libAfterImage inline documentation. ascmap.h - is left to do. - -2001-10-01 sasha - - * completed updating libAfterImage to work with no X display; - cleaned up in preparation for release - -2001-09-28 sasha - - * Updated e-mail address - -2001-09-26 sasha - - * synchin - -2001-09-14 sasha - - * debugged ascp to the degree that all the panels are shown - correctly - -2001-09-13 sasha - - * Added visibility to newly created basic widgets. Upgraded to - typesafe MIN/MAX using prototype from the LInux kernel. Fixed - libAfterImage to do type-safe MIN/MAX. - -2001-09-05 allanon - - * o (ascompose) fixed segfault when free()'ing xml tree - -2001-09-04 allanon - - * o (libAfterImage) added blur_asimage_gauss() to do a gaussian - blur; this - function currently only supports horizontal blurs - o (ascompose) added as an undocumented feature, for - testing only - -2001-09-01 sasha - - * moved ascp into libAfterConf and begun work on getting it fixed - for recent changes to libAfterSTep/Image. Fixed main.c and lib.c - -2001-08-30 sasha - - * Fixed Transparency in asrender - several bugs in mytexture.c that - was. Added MyBackground and DeskBack to look configuration. - added release_asimage_by_name to asimage.c - * added cvsignore to libAfterImage/apps - * Implemented AS customized geometry parsing function; Added stub - for XParseGeometry; Fixe astile and asscale to compile without X - -2001-08-29 sasha - - * Rewrote window hierarchy handling in asrender, and started - implementing transparency handling - * further configure, Makefile and code cleanup to get it to compile - without X - -2001-08-28 sasha - - * Fixed numerous bugs in libAfterImage of various severity. Got - asclook to render default look correctly. - -2001-08-28 allanon - - * o (ascompose) finalized and documented inherited attributes of - : - crefid, x, y, and tint - o (ascompose) added support for compiling --without-x - o (ascompose) new command-line option --root-window; when given, - the - final result image of ascompose will be drawn to the root - window - instead of a new window - * o (ascompose) started adding support for --without-x - o (ascompose) changed the default text spacing to 3; this needs - to be - an option instead - -2001-08-27 sasha - - * fixed freetype detection - * freetype compilation fixes - * fixed magic number usage in ASImage - -2001-08-26 sasha - - * improved configure scripts for libAfterImage to automagically - mkae/install apps - -2001-08-25 sasha - - * fixed asrender and asclook to actually render default look - properly and not segfault in pad_asimage - * fixed ability to load several TRuyeType fonts with different - point size - * added vert and horizontal spacing for fonts; Added ability to - load several TRuyeType fonts with different point size - -2001-08-25 allanon - - * o (ascompose) fixed x,y handling for ; yes, i know i - still - haven't documented them - they're obviously not ready yet :) - -2001-08-22 sasha - - * completed library configure cleanup - adding aslook subdir - -2001-08-20 sasha - - * fixed nasty bug where if dst_x = 0 - and top image is smaller - then bottom one - merge_layer generates garbadge - -2001-08-20 allanon - - * o (ascompose) added documentation for to README - o (ascompose) added "srcx" and "srcy" to - -2001-08-20 sasha - - * Added image cloning/padding functionality to libAfterImage - -2001-08-18 sasha - - * Implemented layer allowing libAfterBase and libAfterImage to work - even without X - -2001-08-17 sasha - - * Added code for Buttons, Icons and empty items to asrennderer. - Fixed bugs in image referencing using ImageManager. Added - render_pad_align_image. - -2001-08-16 sasha - - * Fixed utterly ugly bug in image decompression code where first - position in channel data get corrupted with the data from - adjusten channels. Fixe mytexture tile generation to simply set - image's background to back_color. Added copy_asimage_channel - * Moved back_color into ASImage to maintain image consistency - between subsequent decodings and encodings. Changed back_color - to solid_color in ASImageLayer, to use it only when image is - NULL. Updated everything accordingly. Changed asimage2ximage to - restore missing scanlines based on image's back_color. - * updated ascompose to use init_image_layer for layer - initialization - it was missing back_color to be set to default. - Updated init_image_layer accordingly - -2001-08-15 sasha - - * [no log message] - -2001-08-15 allanon - - * o (ascompose) made attrib "op" optional - o (ascompose) added "merge" to - o (ascompose) added "keep-transparency" to - o (ascompose) added "refid" to all of the options that support - width - and height options - o (ascompose) made attrib "width" and "height" optional - o (ascompose) added new tag and documentation to README - o (ascompose) added new tag and documentation to README - o (ascompose) added new tag and documentation to README - o (ascompose) now uses refcounts to deallocate images when - possible - -2001-08-14 sasha - - * Fixed corners drawing while drawing the inline of the bevel. - Fixed ImageDecoder to allow for im meber to be NULL, but - back_color - not 0 Improved merge_layers to only merge portions - of scanlines that overlap - without padding top scanline. Updated - all blenders accordingly. - * added bevel with solid inlines; Fixed gradiented bevel drawing on - very large distances; updated deps - -2001-08-13 sasha - - * Implemented create/init_image_layers Implemented AddLabel in - asrenderer Fixed mystyle_draw_text - -2001-08-10 sasha - - * added sanity checks to bevel parameter. Need to fix bevel - increment calculations for inline. - -2001-08-10 allanon - - * o sync commit so sasha can see a problem with - -2001-08-10 sasha - - * Split asimage.c into 3 files - asimage.c, transform.c and - ximage.c, with asimage.h being split up accordingly. Fixed bug - in create_asimage code to check for validity of compression - parameter. Fixed introduced bug in merge_layers where we forgot - to skip first layer in the main loop. - -2001-08-09 sasha - - * Mostly implemented window background rendering and layers merging - in asrender code. - -2001-08-08 sasha - - * Changed license of libAfterBase and libAfterImage to LGPL - -2001-08-08 allanon - - * o (ascompose) reordered usage message to be alphabetical - o (ascompose) upped version to 1.2 - o (ascompose) added automagical output format detection based on - extension - o (ascompose) added id parameters to all xml tags - o (ascompose) added and xml tags, and docs to - README - -2001-08-07 sasha - - * Updated ascompose with ability to save images into any supported - file format(kowalski) Also added ability to write out image - without displaying it first. - * Fixed bug found by k0walski where file export filters would - return False even if save was successful. - * Updated MyTexture, MyLook and MyStyle to use libAfterImage. - Rewrote session management a bit for saner look/feel management. - Added CursorManager code. Added asclook app to libAfterConf to - provide for preview of arbitrary looks. Fixed several bugs in - Image loading code. - -2001-07-26 sasha - - * Finally brought giflib to its knees by implementing lots of - cludges to work around its bugs. Thank god gif's colormap is - stored uncompressed! Now libAfterImage can both read and write - multiimage gif files. HipHip Hooray! - -2001-07-25 sasha - - * playing cat and mouse with giflib bugs - and there are plenty of - those. We'll need to move portions of it into libAfterImage to - ease the pain. - * Minor cleanup in gif writer - -2001-07-24 sasha - - * no message - * fixed several bugs in colormap generation, and implemented gif - output filter ( sort of ) - -2001-07-23 sasha - - * completed colormapping code allowing for different degrees of - dithering - -2001-07-22 sasha - - * polished colormap calculation quite a bit and made it to allocate - just the right amount of colors by adding more passes - -2001-07-20 sasha - - * completed implementation of quantization and colormapping of - images. Debugged, but still can be optimized for speed. - -2001-07-19 sasha - - * Implemented some experimetal code to create colormapped images - and allow for dithering and optimum color selection. - -2001-07-17 sasha - - * Rewrote MyLook from config generation . Updated MyStyles to use - ASImages and ASFonts - -2001-07-16 sasha - - * Added image reference to libAfterImage Fixed font dereferencing ( - see release_font() ). Started implementation of libAfterImage - interface in libAfterStep. - -2001-07-13 sasha - - * Added get_drawable_size to afterbase.c (damn allanon :) Added - define for mystrcmp Added check for libAfterBase presence before - setting output threshold in asmerge - * Fixed clobbered variable in export.c; Fixed missing - SHOW/START_TIME in afterbase.h.in Added MMX notice to README's. - * Updated docs to reflect recent API changes - * Upped library version to 0.81 - * Fixed libAfterImage to compile nicely when libAfterBase is not - available - -2001-07-13 allanon - - * o added xml tag to ascompose, and documentation in - README - -2001-07-13 sasha - - * added mirroring capability to asflip - -2001-07-12 sasha - - * Implemented mirror_asimage() for image mirroring (as you could - have guessed :) - -2001-07-12 allanon - - * o added xml tag to ascompose, and documentation to - README - o added xml tag to ascompose, and documentation to - README - o added test.xml, which contains the xml used during testing - -2001-07-12 sasha - - * fixed compile bug in ASImage2gif - * Added templaites for image export filters. Implemented RGB and - greyscale JPEG image writing. Implemented RGB and greyscale PNG - image writing with or without alpha channel. Added usefull - SHOW_TIME and START_TIME macros to libAfterBase - -2001-07-11 sasha - - * disabled doc.html generation on make install - that was stupid to - try and do that. - * Added final astext tutorial comments. Reupdated documentation. - * final fix to installation and Makefiles - -2001-07-11 allanon - - * added ascompose, an XML-based image composition tool - -2001-07-11 sasha - - * added afterimag.h to incs - * fixed headers locating in /usr/local/include - * fixed installation of afterimage-libs script - * fixed standalon configure run - * fixed doc installation in Makefile - * updated Makefile to install include files as well - * fixed configure in libAfterImage to have separate enablers for - static and shared libs - -2001-07-10 sasha - - * Updated documentation abit to refelect recent code changes and - make it easier to link from main index page. - * fixed bug in xpm parser where spaces would get treated - incorrectlt in colormap; added READMEs; - -2001-07-09 sasha - - * Added functionality to move_asimage_channel to be able to move to - arbitrary channels from arbitrary channels. Added documenting - comments to astext.c and fixed text layout abit. - * Fixed parse_argb_color. Added options to astile and asflip for - easier operation. Fixed asgrad to treat gradient type well, if - gradient is not specified. Added few more points to asgrad - sample gradient to create better illusion of the rainbow. - * Added report of the scale factor to asscale - * Changed astile to tile to twice the size of the image - * Fixed bug in 3D text rendering causing us to skip scanline - inbetween lines of text. Added sample image rose512.jpg, and - TTF font: test.ttf. Added nice defaults to all the sample apps, - so that ppl can see libAfterImage in its full beauty. - * Adde Usage to all the examples. Fixed segfault in asscale. Added - error message on image file not found. Added texturized text - sample images. - -2001-07-08 sasha - - * fixed parse_argb_color to check for dpy not being NULL - to avoid - segfaults, babe - * added usage display to asflip and asgrad and fixed some other - places where parse_argb_color would be called prior to dpy - initialized - * added clocking to draw_text; added usage and more sophisticated - usage to astext - -2001-07-07 sasha - - * fixed 3D drawing and implemented all 6 modes - -2001-07-06 sasha - - * fixed glyph compression again; Started implementing 3D text. - * Fixed bug in asimage.c where fake_im was not initialized; - Corrected glyph compression code - * asfont fixin - * fixed layers merging to correctly draw the background layer when - image is missing; Fixed spacing calculations, while drawing text - -2001-07-05 sasha - - * Temporarily plugged bug in layer merging descovered by allanon, - when bottommost layer does not have any image in it. - * Reimplemented image output to allow for flexible support for many - image formats - right now it could be ASImage itself, XImage, - mask XImage and ARGB32. Surprisingly that simplified code quite - abit. Fixed ugly bug in create_asimage. Completed and debugged - astext tutorial. - * fixed text size calculations; fixed (almost) bevel drawing - - need to think about what to do with clip_width/height in Layer - specs - -2001-07-04 sasha - - * fixed lots of bugs in glyph compressing and rendering, still - something is wrong with size calculation func. Added - move_asimage_channel to swap channels on images - -2001-07-03 sasha - - * implemented astext properly - * implemented asgrad, asflip and astext. Althou astext still needs - some work. - * added prototypes for asflip, asgrad and astext - examples/tutorials/testapps to the libAfterIMage suit - -2001-07-02 sasha - - * Completed ASMerge implementation. Used it to debug all the - merging routines. Everything works perfect now. Added - doc/html/asmerge.html - another tutorial. Added - list_scanline_merging function to blender.c so that we can show - descriptions on different merging methods. - * Added ASMerge example, and added translator from function name to - function for scanline merging/blending. - -2001-06-29 sasha - - * Added ASScale and ASTile examples with documentation and stuff. - Fixed bug in asimage.c causing artifacts when image is tiled with - TOP quality. cleabed up cvsignore in include/ - * fixed and simplified configure script for examples to - libAfterImage. Have a good day :) - -2001-06-28 sasha - - * Added documenting comments to asview.c so it generates nice - little Tutorial as the result. Added lots of X functions to xref - files, so now all the source code is very nicely crossreferenced. - Added references to asview to other headers etc. - -2001-06-27 sasha - - * Completed documenting asfont.h Added afterimage.h with library - overview got rid of old doc files added freetype and X11 xrefs so - that docs are nicely crosslinked with X docs - -2001-06-26 sasha - - * asfont.h documentation 50% done - * added Makefile targets fopr autogeneration of documentation in - man and HTML formats. Added installation procedure for those. - -2001-06-25 sasha - - * Documented blender.h and import.h - asfont.h to go. Also it - sound like a good idea to add afterimage.h with overview notes - about libAfterImage and references to components. - -2001-06-24 sasha - - * completed fixing libraries includes - * rewrote libraries includes generation; fixed freetype checking to - skip old garbadge left over in X11R6 dir - -2001-06-22 sasha - - * Completed documenting asimage.h and asvisual.h. asfont.h and - import.h to go - * fixed libAfterImage include to always use -I gcc flag - -2001-06-21 sasha - - * MOre documentation writing - ASImage.h is almost done. - -2001-06-21 owsla - - * added stop_image_output() to asimage2mask_ximage() - -2001-06-21 sasha - - * got asview to compile cleanly and find all the relevant - libraries - need to think about simplifying configure scripts and - headers there - -2001-06-20 owsla - - * plugged a mem leak, asimage2ximage() wasn't doing - stop_image_output() on it's ASImageOutput struct - -2001-06-20 sasha - - * asimage.html and asimage.man updates - * Implemented proper generation of mask XImage (1bpp) - -2001-06-19 sasha - - * more doc - * Implemented ARGB->pixel conversion for 32 and 24 bit True color - visual Fixed parse_argb_color to correctly treat 12 digit color - value as 48bit RGB. More libAfterImage documenting - * Fixed bug in find_file preventing it from finding files when not - NULL search path is specified. Fixed bug in asimage2pixmap - causing it to use wrong gc variable. Added more documentation to - asimage.h and respectively to asimage.html - -2001-06-18 sasha - - * Added lots of self documenting comments to - libAfterImage/asimage.h to allow for automagic documentation - generation using robodoc package. Seems to be the only package - that works decently. - -2001-06-17 sasha - - * started implementing sample repository of example libAfterImage - apps - -2001-06-15 sasha - - * Added prototypes of the man pages for libAfterImage - -2001-06-14 sasha - - * added MMX enabling switch to libAfterImage configure - * Completed Pseudo-color support with colormap allocation and - ximage handling. Added create_asimage and destroy_asimage for - convinience. Added missing stuff to libAfterImage/afterbase.h to - make it completely independent. libAfterImage thus should be - ready for release - only to write up some docs :) - -2001-06-13 sasha - - * completed flip-flopping code. Added show_debug to show_* series - in libAfterBase/output.c started working on collor allocation on - PseudoColor visuals - -2001-06-12 sasha - - * completed implementation of image alpha beveling. completed - implementation of image flipping - need some cleanup thou to - allow for tiling. - -2001-06-11 sasha - - * fixed configure to produce correct dependencies - * no message - * Hopefully fixed memory allocations audit on libAfterBase. - * Added ASImageBevel to allow for transparent bevelling of images - while merging layers. Hopefully fixed X libs in configure script - - need to rerun autoconf - * added configclean target to the top level makefile; fixed - libraries makefiles to correctly generate .depend files - * fixed configure scripts to not do extra checks when invoked from - one another - -2001-06-10 owsla - - * updated .cvsignore files - -2001-06-10 sasha - - * got rid of old image loading stuff. LoadImageWithMask moved into - resources.h and is now simple shortcut to libAfterImage loader - -2001-06-09 sasha - - * made test to compile; Fixed several bugs in libAfterImage; - optimized 2bpp handling in xpm code; builtin xpm handler is about - 2 times as fast as libXpm on small images and 5 times on larger - ones - -2001-06-08 sasha - - * configure fixes - * updated configure scripts - * further progress - src/test compiles now, but need to redo - libAfterImage/configure - * fixed compilation bug in import.c - * rebuilt configure scripts - * updated configure scripts to reflect addition of the xpm parsing - code - * Completed custom xpm implementation. Needs to be debugged thou. - * hopefully fixed main configure script to gracefully handle - libraries configuration as well. MOved configure.h and some other - headers into include dir, so it could be used by modules - -2001-06-07 sasha - - * Fixed MyName requests in selfdiag.c; Added xpm.c to implement - custom xpm handling code - appears to be rather simple and - effective. Most of the things are implemented, except for top - level routine. - * cleaned configure script for libafterimage. added afterimage-libs - script to print list of LD_FLAGS for linking with libafterimage - -2001-06-06 sasha - - * fixed bug found by allanon when asimage2ximage would produce - black ximage due to unset flags in scanline - -2001-06-04 owsla - - * updated configure - * updated the .cvsignore files - -2001-06-04 sasha - - * fixed bug in configure --with-jpeg - * added missing .depend - * sorted out compilation problems, and test now builds with new - libAfterImage - -2001-06-03 sasha - - * got libAfterImage to compile - -2001-06-02 sasha - - * hopefully resolved libAfterImage dependancy on libAfterBase - -2001-06-01 sasha - - * separated libAfterImage files from the rest of the crowd - * started up libAfterImage - -2001-05-30 sasha - - * Prototyped ASRenderer interface - * completed fixing old lib files to compensate for file relocation. - There needs to be something done to Mkaefiles and configure to - correctly set up include paths and libraries. - -2001-05-28 sasha - - * Split ASVisual from ScreenInfo and rearranged ARGB32. Added - ASGradient to asimage.h and made gradient_t to be a synonym to - it. That should allow for better library independancy - visual - will go with libAfterImage while ScreenInfo will move into - libAfterStep , or, possibly will split up even more. Goal is to - make libAfterImage completely independent from everything else. - -2001-05-23 allanon - - * Updated FSF snail mail address. - -2001-05-12 sasha - - * added code to check for valid channels while flipping - -2001-05-10 sasha - - * Completed gradients drawing code. Started on flipping code. - Added direction reverse to output method. - -2001-05-09 sasha - - * Implemented vertical gradient drawing. sorted out relationship - between channel numbering and ARGB32 component order - its the - same now. - * fixed mono line encoding to add zero terminator at the end; fixed - scanline back_color initialization to have alpha at 0xFF; fixed - decoration layouting to not use stack memory in linked list; - fixed property event handler to initialize variable to NULL; - Afterstep now starts , althou does not do anything usefull - -2001-05-08 sasha - - * coded gradients drawing using ASImages with smoothing and - dithering - works very blasted fast. Fixed numerous include's - issues - -2001-05-07 sasha - - * fixed create_screen_window for InputOnly windows fixed bug in - screen initialization where Colormap ID would get lost fixed bug - in desktop creation code where desktop->scr would never get - initialized. Added show_progress function to work similarly to - show_warning/error Rearranged thresholds for output verbosity - Added stdargs.h to import.c - suggested by Sean Dague - -2001-05-04 sasha - - * completed ASFont implementation as needed at the moment - there - will need to be some work done in order to adapt it to locale - support.( as well as in several other places). changed glyph - compression algorithm once again to run length encode only 0s and - FFs, and store rest in raw format. That allows to cut down on - memory since we don't use 2 bytes anymore. 3 step antialiasing - works now. Off to image rotation and gradient drawing. - -2001-05-03 sasha - - * Improved glyph compression algorithm so now it actually reduces - size, even on ery small fonts. Tryed to implement additional - glyph smoothing, but something is wrong - disabled for now. - -2001-05-02 sasha - - * fixed font drawing to group glyphs as close together as possible - - make for much nicer effect. - * debugged X11 fonts loading and drawing. Still need to do - something about negative left bearings - ought to really offset a - pen to overlap charcters - -2001-05-01 sasha - - * Implemented antialiasing for native X fonts - still needs some - debuggin. - -2001-04-30 sasha - - * added RLE compression to the font glyph cache. added character - range specification for the font. added right-to-left writing - order on per font basis. - -2001-04-27 sasha - - * implemented text drawing using precached TTF fonts -- needs - addition of locale support in future. Fixed image merging to do - clipping correctly. Added image background color - * fixed freetype headers problems and a bug in font hashing - -2001-04-26 sasha - - * started implementing font manager and freetype support - -2001-04-25 sasha - - * moved scanline merging functions into separate file - * fixed most blending function so not to tresspass alpha channel - boundaries. Added tint_scanlines and implemented dissipation - * fixed bug in image loading where piexls would get shifted by one - to the right. added 14 image blending functions - almost - matching that of the GIMP's capabilities, except for multiply and - divide modes, which I don't see much sense in. Added - RGB->HSV->RGB and RGB->HLS->RGB conversion functions. - -2001-04-24 sasha - - * cleaned up output/encoding functionality. Added quality - parameters to dynamically adjust quality on per image basis. - Implemented alpha blending and generic layer merging framework. - -2001-04-23 sasha - - * debugged tiling functionality and optimized it so not to do - repeated compression on the same data. Added compression ratio - specification on per image basis. OPtimized buffer copy to use - 32bit data transfer. Implemented tinting( as a part of tiling - process ). - * debugging tiler - -2001-04-22 sasha - - * added tile_image() - needs debugging - * ASImageDecoder - -2001-04-20 sasha - - * added TIFF import and implemented generic image loading function - with search capabilities and subimage loading. Fixed two more - bugs in image scaling. - * added GIF import filter; added configure code to detect gif and - tiff libraries - -2001-04-19 sasha - - * .CUR is the same as .ICO only type = 2 - * Added support for .PNM, .PPM, .ICO, .BMP image file formats - - TIFF and GIF to go - -2001-04-18 sasha - - * xcf image loading now works, but only gets you first layer with - the same size as whole image. Need to implement layers merging - for ASImages to get complete support for GIMP's xcf files - * fixed bug in xcf channel loading - theer are no such thing as - channel type - -2001-04-17 sasha - - * most of the preparation work for xcf reading is done - now off to - actually create ASImage from it. added code to poupulate - ASScanline with 0's where data is not available; - -2001-04-16 sasha - - * minor quality tweaks in rations 1-2 scaling up. Started - implementing ASImageDecoder for automatic tinting/tiling - * IMplemented JPEG input filter for ASImage. Fixed long standing - bug in image scaling causing weirdness in scaling UP with small - ratios. Started implemntation of XCF file reader. - -2001-04-15 sasha - - * implemented png file reader and fixed blatant bug in scale image - up where first line got garbadge in it - -2001-04-13 sasha - - * compilation fixes - * Implemented xpm loading into asimage. Updated asimage to - correctly use ScreenInfo. implemented create_screen_pixmap and - create_screen_ximage - * fixed test abit to not spit lots of warnings - -2001-04-08 sasha - - * fixed bugs in scaling down code with ratio > 2; It appears that - you can create windows with different visual only if you create - new colormap and allocate border color from it as well. Fixed - screen.c accordingly. We keep black and white pixels and colormap - in ScreenInfo now - should use it instead of X macros - -2001-04-06 sasha - - * implemented workaround for some stupid X servers that denys you - your constitutional right to use whatever Visual you like. - * couple bugfixes for new visual handling code. moved - ximage->scanline->ximage code from asimage.c to screen.c still - need to implement PseudoClor handling - * hopefully fixed bug in 2x scaling up code - -2001-04-05 sasha - - * no message - * reworked ScreenInfo abit to include visual info. Added screen.c - to libafterstep to collect together all the Screen/display - related stuff - ConnectX, MyXErrorHandle, and several new things - : init_screen and destroy_screen. nolock_mods has been moved - outside of the ScreenInfo as it is per-display and not per-screen - stuff. all_screens global variable holds pointers to all - ScreenInfo structrures for available screens. Added - query_visual_info to try and obtain best possible visual for - AfterStep to use. Need to move ximage->as->ximage conversion - stuff into screen.c. ConnectX now takes only one parameter - - pointer to ScreenInfo is discontinued - * same old Ximage cleanup - -2001-04-04 sasha - - * asimage->ximage debugging again - this time about 50% performance - increase. - * more optimization to ximage output algorithm - that was the last - of it I'm sick and tired from this stuff - -2001-04-03 sasha - - * Some tweaks to XImage writing code to speed things up - we were - spending upto 30% of time writing XImages - unacceptable. - * fixed bug in line interpolation causing stripy artifacts in - scaling up - * mmx debugged - -2001-04-02 sasha - - * Added some MMX inline assembly to image scaling code to hopefully - make it faster - need to verify if that indeed is the case. - * aaa - -2001-04-01 sasha - - * scaling speed optimizations - -2001-03-31 sasha - - * debugged new scaling code - scale up is rather nice even with - huge ratio - check out src/test - -2001-03-30 sasha - - * Implemented complete scaling Up procedure for arbitrary ratio - - if it'll work then similar stuff will go for 1-2 and 2-3 ratios. - Added reshape_winlist to WinList to actually generate layout of - titlebars based on WinList data and store pointers to them in - appropriate place in WMDecor structures. It now needs to be - debugged as a prototype for other modules. - * debugged scaling down algorithm - it now works and scale things - down rather nicely. Thus we have a proof of concept and can - proceed on to scaling up - which is mopstly implemented already - -2001-03-29 sasha - - * completed implementation of scaling down of ASImages. Added - dithering capabilities to ASImage->XImage conversion to hopefully - produce better results on 16bpp and 15bpp Fixed bug in ASWinLIst - message processing to create WinList if it did not exist. Fixed - Bug in afterstep to initialize handlers in main window list to - correct functions. - * defined structure of high level scaling API - -2001-03-28 sasha - - * Added AS message reading/partiall handling to new WinList. Moved - get_window_* functions into aswinlist.c Changed the way - process_message is called - it now takes ASMessage * as a param. - Made everything compiling. - * some theory investigation into up scaling algorithms with - smoothing - -2001-03-27 sasha - - * the best variant of compression algorithm - average compression - ratio is about 75for highly random images(nature) and 30for - regular images (naked body, etc.); no off to more exciting things - -2001-03-26 sasha - - * no message - * fixed compression code - -2001-03-24 owsla - - * removed static keyword from libasimage_decode_line, this was - preventing it from being exported in the lib, which made the test - program fail - -2001-03-23 sasha - - * optimized asimage decompression algorithm scaling down algorithm - implemented/. - * extensive asimage debugging - compression now seems to work fine - -2001-03-22 sasha - - * Completed implementation of Pixmap->ASImage->Pixmap cycle Now off - to debugging and implementing of scaling/alpha-blending/etc. - -2000-12-12 sasha - - * libasimage has been renamed to libasGUI - -2000-09-17 sasha - - * make_indent - -2000-05-15 sasha - - * asImageFromXImageTest diff --git a/graf2d/asimage/src/libAfterImage/Makefile.in b/graf2d/asimage/src/libAfterImage/Makefile.in deleted file mode 100644 index 81588f200a407..0000000000000 --- a/graf2d/asimage/src/libAfterImage/Makefile.in +++ /dev/null @@ -1,406 +0,0 @@ -# -# Copyright (c) 2001, Sasha Vasko -# Copyright (c) 1998, Guylhem AZNAR -# - -subdirs = libjpeg libpng libungif zlib - -LIBJPEG_OBJS = libjpeg/jaricom.o libjpeg/jcarith.o libjpeg/jdarith.o \ - libjpeg/jcapimin.o libjpeg/jcapistd.o libjpeg/jccoefct.o \ - libjpeg/jccolor.o libjpeg/jcdctmgr.o libjpeg/jchuff.o \ - libjpeg/jcinit.o libjpeg/jcmainct.o libjpeg/jcmarker.o \ - libjpeg/jcmaster.o libjpeg/jcomapi.o libjpeg/jcparam.o \ - libjpeg/jcphuff.o libjpeg/jcprepct.o libjpeg/jcsample.o \ - libjpeg/jctrans.o libjpeg/jdapimin.o libjpeg/jdapistd.o \ - libjpeg/jdatadst.o libjpeg/jdatasrc.o libjpeg/jdcoefct.o \ - libjpeg/jdcolor.o libjpeg/jddctmgr.o libjpeg/jdhuff.o \ - libjpeg/jdinput.o libjpeg/jdmainct.o libjpeg/jdmarker.o \ - libjpeg/jdmaster.o libjpeg/jdmerge.o \ - libjpeg/jdpostct.o libjpeg/jdsample.o libjpeg/jdtrans.o \ - libjpeg/jerror.o libjpeg/jfdctflt.o libjpeg/jfdctfst.o \ - libjpeg/jfdctint.o libjpeg/jidctflt.o libjpeg/jidctfst.o \ - libjpeg/jidctint.o libjpeg/jquant1.o \ - libjpeg/jquant2.o libjpeg/jutils.o libjpeg/jmemmgr.o libjpeg/jmemnobs.o \ - libjpeg/transupp.o - -LIBPNG_OBJS = libpng/png.o libpng/pngset.o libpng/pngget.o libpng/pngrutil.o \ - libpng/pngtrans.o libpng/pngwutil.o libpng/pngread.o libpng/pngrio.o \ - libpng/pngwio.o libpng/pngwrite.o libpng/pngrtran.o \ - libpng/pngwtran.o libpng/pngmem.o libpng/pngerror.o \ - libpng/pngpread.o - -ZLIB_OBJS = zlib/adler32.o zlib/compress.o zlib/crc32.o \ - zlib/gzio.o zlib/uncompr.o zlib/deflate.o \ - zlib/trees.o zlib/zutil.o zlib/inflate.o \ - zlib/infback.o zlib/inftrees.o zlib/inffast.o - -LIBUNGIF_OBJS = libungif/dgif_lib.o libungif/egif_lib.o libungif/gifalloc.o \ - libungif/gif_err.o libungif/gif_hash.o - -AFTERIMAGE_OBJS= @AFTERBASE_C@ asimage.o ascmap.o asfont.o asstorage.o \ - asvisual.o blender.o bmp.o char2uni.o draw.o export.o imencdec.o import.o \ - scanline.o transform.o ungif.o xcf.o ximage.o xpm.o \ - afterrootpngwrite.o - -################################################################ -# library specifics : - -LIB_INCS= afterimage.h afterbase.h ascmap.h asfont.h asim_afterbase.h \ - asimage.h asstorage.h asvisual.h blender.h bmp.h char2uni.h \ - draw.h export.h imencdec.h import.h scanline.h transform.h ungif.h \ - xcf.h ximage.h xpm.h xwrap.h \ - afterrootpngwrite.h - -LIB_OBJS= @JPEG_OBJS@ @ZLIB_OBJS@ @PNG_OBJS@ @UNGIF_OBJS@ $(AFTERIMAGE_OBJS) - -APPS_SRCS=apps/common.c apps/ascompose.c apps/asview.c \ - apps/asscale.c apps/astile.c apps/asmerge.c \ - apps/asgrad.c apps/asflip.c apps/astext.c - -APPS_INCS=apps/common.h - -APPS_DEPS=@LIBPROG@ $(LIB_OBJS) $(LIB_INCS) $(APPS_SRCS) $(APPS_INCS) config.h - -# end specifics -################################################################ -# generic makefile stuff : - -LIB_DIR_NAME = libAfterImage -LIB_NAME = LIBAFTERIMAGE -LIB_STATIC = libAfterImage.a -LIB_SHARED = libAfterImage.so -LIB_SHARED_CYG = cygAfterImage.dll -LIB_SHARED_CYG_AR = libAfterImage.dll.a -LIBVER = 0.99 -LIBVERMAJOR = 0 - -CC = @CC@ -CCFLAGS = @CFLAGS@ @MMX_CFLAGS@ -# -march=pentiumpro -mcpu=pentiumpro -EXTRA_DEFINES = @DEFINE_XLOCALE@ - -RANLIB = @RANLIB@ -AR = ar cq -CP = @CP@ -MV = @MV@ -RM = @RM@ -RMF = @RM@ -f -MKDIR = @MKDIR@ -p -FIND = @FIND@ -XARGS = @XARGS@ -LDCONFIG = @LDCONFIG@ -ROBODOC = robodoc -LN_S = @LN_S@ - -YACC = @YACC@ -LEX = @LEX@ -YACCFLAGS = -d -LEXFLAGS = - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL@ -s -m 755 -INSTALL_DATA = @INSTALL@ -m 644 -INSTALL_HEADER = @INSTALL@ -m 644 -INSTALL_LIB = @INSTALL@ -m 755 -INSTALL_SCRIPT = @INSTALL@ -m 755 - -INCS_EXTRA = @XPM_CFLAGS@ @JPEG_CFLAGS@ @PNG_CFLAGS@ @GIF_CFLAGS@ @TIFF_CFLAGS@ @SVG_CFLAGS@ @TTF_INCLUDES@ -INCS_X = @X_CFLAGS@ -INCS_PRIVATE = -INCLUDES = $(INCS_EXTRA) $(INCS_PRIVATE) $(INCS_X) - -USER_LD_FLAGS = @user_ldflags@ -LIBS_X = @x_libs@ -LIBS_XEXTS = -LIBS_TEST = @AFTERIMAGE_TEST_LIBS@ -LIBS_AFTERIMAGE = @AFTERIMAGE_LIB_LIBS@ -LIBRARIES = $(LIBS_AFTERIMAGE) $(LIBS_X) $(LIBS_XEXTS) -LIBRARIES_TEST = $(LIBS_TEST) $(LIBS_X) $(LIBS_XEXTS) - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -LIBDIR = $(DESTDIR)@libdir@ -INCLUDEDIR = $(DESTDIR)@includedir@ -AFTER_INC_DIR = $(DESTDIR)@includedir@/$(LIB_DIR_NAME) -AFTER_BIN_DIR = $(DESTDIR)@bindir@ -AFTER_MAN_DIR = $(DESTDIR)@mandir@/man3 -AFTER_APP_MAN_DIR = $(DESTDIR)@mandir@/man1 -AFTER_SHAREDIR = $(DESTDIR)@datadir@/$(LIB_DIR_NAME) -AFTER_DOC_DIR = $(AFTER_SHAREDIR)/doc - -# We want to build both static and dynamic libs, as some service apps may need -# static library as they gets run at compile time (ASDocGen for example) -# but we only install whats selected -all: $(LIB_STATIC) @LIBPROG@ $(INSTALLONBUILD) apps - -install.bin: - -install.lib: @LIBPROG@ @LIBINSTALL@ install.inc - -mkdir: - @(if [ ! -d $(AFTER_BIN_DIR) ] ; then $(MKDIR) -p $(AFTER_BIN_DIR); fi; \ - if [ ! -d $(LIBDIR) ] ; then $(MKDIR) -p $(LIBDIR); fi \ - ) - -install.static: mkdir - $(INSTALL_SCRIPT) afterimage-libs afterimage-config $(AFTER_BIN_DIR) - @(if [ -d $(LIBDIR) ] && [ -w $(LIBDIR) ]; then \ - echo "$(INSTALL_LIB) $(LIB_STATIC) $(LIBDIR)"; \ - $(INSTALL_LIB) $(LIB_STATIC) $(LIBDIR); \ - fi \ - ) - -install.script: - -install.dyn: mkdir - @( echo "$(INSTALL_LIB) $(LIB_SHARED).$(LIBVER) $(LIBDIR)"; \ - $(INSTALL_LIB) $(LIB_SHARED).$(LIBVER) $(LIBDIR); \ - $(INSTALL_SCRIPT) afterimage-libs afterimage-config $(AFTER_BIN_DIR); \ - $(RM) -f $(LIBDIR)/$(LIB_SHARED).$(LIBVERMAJOR) $(LIBDIR)/$(LIB_SHARED); \ - $(LN_S) -f $(LIB_SHARED).$(LIBVER) $(LIBDIR)/$(LIB_SHARED).$(LIBVERMAJOR); \ - $(LN_S) -f $(LIB_SHARED).$(LIBVERMAJOR) $(LIBDIR)/$(LIB_SHARED); \ - ) - -install.cyg: mkdir - @( echo "$(INSTALL_LIB) $(LIB_SHARED_CYG) $(AFTER_BIN_DIR)"; \ - $(INSTALL_LIB) $(LIB_SHARED_CYG) $(AFTER_BIN_DIR); \ - echo "$(INSTALL_LIB) $(LIB_SHARED_CYG) $(LIBDIR)"; \ - $(INSTALL_LIB) $(LIB_SHARED_CYG) $(LIBDIR); \ - echo "$(INSTALL_LIB) $(LIB_SHARED_CYG_AR) $(LIBDIR)"; \ - $(INSTALL_LIB) $(LIB_SHARED_CYG_AR) $(LIBDIR); \ - echo "$(INSTALL_SCRIPT) afterimage-libs afterimage-config $(AFTER_BIN_DIR)"; \ - $(INSTALL_SCRIPT) afterimage-libs afterimage-config $(AFTER_BIN_DIR); \ - ) - -install.inc: - @(if [ -d $(AFTER_INC_DIR) ]; then \ - echo "$(RM) $(AFTER_INC_DIR)/*"; \ - $(RM) $(AFTER_INC_DIR)/*; \ - else \ - if [ -d $(INCLUDEDIR) ]; then \ - echo "$(MKDIR) $(AFTER_INC_DIR)"; \ - if $(MKDIR) $(AFTER_INC_DIR); then \ - echo " ">/dev/null; \ - else \ - echo "failed to create include directory: $(AFTER_INC_DIR)"; \ - fi; \ - else \ - echo "$(MKDIR) $(INCLUDEDIR)"; \ - if $(MKDIR) $(INCLUDEDIR); then \ - echo "$(MKDIR) $(AFTER_INC_DIR)"; \ - if $(MKDIR) $(AFTER_INC_DIR) >/dev/null; then \ - echo " ">/dev/null; \ - else \ - echo "failed to create include directory: $(AFTER_INC_DIR)"; \ - fi; \ - else \ - echo "failed to create include directory: $(INCLUDEDIR)"; \ - fi; \ - fi; \ - fi; \ - if [ -d $(AFTER_INC_DIR) ]; then \ - echo "installing libAfterImage headers using command - "; \ - echo " \"$(INSTALL_HEADER)
$(AFTER_INC_DIR)\" :"; \ - for file in $(LIB_INCS) ; do \ - echo -n "$$file "; \ - $(INSTALL_HEADER) $$file $(AFTER_INC_DIR); \ - done; \ - echo ""; echo "Done."; \ - fi \ - ) - -install.apps: install.lib - @(if test -d apps; then cd apps; $(MAKE) install || exit 1; fi) - -# uninstallation targets : -# -STATIC_LIB_FILES=$(LIBDIR)/$(LIB_STATIC) -DYN_LIB_FILES=$(LIBDIR)/$(LIB_SHARED).$(LIBVERMAJOR) $(LIBDIR)/$(LIB_SHARED) $(LIBDIR)/$(LIB_SHARED).$(LIBVER) -CYGWIN_LIB_FILES=$(AFTER_BIN_DIR)/$(LIB_SHARED_CYG) $(LIBDIR)/$(LIB_SHARED_CYG) $(LIBDIR)/$(LIB_SHARED_CYG_AR) - -uninstall.static: - @for i in $(STATIC_LIB_FILES); do \ - if [ -f $$i ] ; then echo $(RMF) $$i; $(RMF) $$i; fi; \ - done - -uninstall.dyn: - @for i in $(DYN_LIB_FILES); do \ - if [ -f $$i ] ; then echo $(RMF) $$i; $(RMF) $$i; fi; \ - done - -uninstall.cyg: - @for i in $(CYGWIN_LIB_FILES); do \ - if [ -f $$i ] ; then echo $(RMF) $$i; $(RMF) $$i; fi; \ - done - - -uninstall.inc: - @if [ -f $(AFTER_BIN_DIR)\$(CONFIG_SCRIPT) ] ; then \ - echo "$(RMF) $(AFTER_BIN_DIR)\$(CONFIG_SCRIPT)"; \ - $(RMF) $(AFTER_BIN_DIR)\$(CONFIG_SCRIPT); \ - fi; \ - if [ -d $(AFTER_INC_DIR) ]; then \ - echo "$(RMF) $(AFTER_INC_DIR)/*"; \ - $(RMF) $(AFTER_INC_DIR)/*; \ - fi; \ - if [ -d $(INCLUDEDIR)/$(LIB_DIR_NAME) ]; then \ - echo "$(RMF) $(INCLUDEDIR)/$(LIB_DIR_NAME)"; \ - $(RMF) $(INCLUDEDIR)/$(LIB_DIR_NAME); \ - fi - -uninstall.bin: - @for i in $(LIB_APPS); do \ - if [ -f $(AFTER_BIN_DIR)\$$i ] ; then echo $(RMF) $(AFTER_BIN_DIR)\$$i; $(RMF) $(AFTER_BIN_DIR)\$$i; fi; \ - done - -uninstall.apps: - @(if test -d apps; then cd apps; $(MAKE) uninstall || exit 1; fi) - -uninstall.lib: @LIBUNINSTALL@ uninstall.inc uninstall.apps - -uninstall.man: - -uninstall.script: - -clean: - $(RMF) $(LIB_SHARED) $(LIB_SHARED_CYG) $(LIB_SHARED_CYG_AR) $(LIB_STATIC) *.so.* *.so *.o *~ *% *.bak \#* core ; \ - for I in ${subdirs}; do $(RMF) $$I/*.o $$I/*.obj $$I/*.bak; done - @(if test -d apps; then cd apps; $(MAKE) clean || exit 1; fi) - -distclean: clean - $(RMF) $(LIB_SHARED) $(LIB_SHARED_CYG) $(LIB_SHARED_CYG_AR) $(LIB_STATIC) *.o *.so.* *~ *% *.bak \#* *.orig core Makefile - @(if test -d apps; then cd apps; $(MAKE) distclean || exit 1; fi) - -indent: - @SRCS=`echo "$(AFTERIMAGE_OBJS) " | sed "s/.o /.c /g"`; \ - if test "x$$SRCS" == "x"; then exit; fi; \ - for i in $$SRCS; do \ - if (indent -di14 -ts4 -i4 -l120 -lc80 -bad -nbbb -bli0 -c48 -cd48 -ce -cli1 -ncs -nbs -nbbo -hnl < $$i > /tmp/$$i); then \ - echo "indent $$i"; \ - mv /tmp/$$i $$i; \ - fi; \ - done ; \ - (if test -d apps; then cd apps; $(MAKE) indent || exit 1; fi ) - -deps: - @echo -n > .depend ; \ - buf="" ; \ - SRCS=`echo "$(AFTERIMAGE_OBJS) " | sed "s/.o /.c /g"`; \ - echo -n $(LIB_NAME)_OBJS = > .shared ; \ - for file in $$SRCS; do \ - echo " \\" >> .shared ; \ - echo -n ' $$('$(LIB_NAME)_PATH')'/$$file >> .shared ; \ - if test "x$$buf" != "x"; then \ - echo $$buf >>.depend ; \ - echo >>.depend ; \ - fi; \ - buf="./"`echo "$$file " | sed "s/.c /.o /g"`: ; \ - for d in `grep "#include \"" < $$file | awk -F \" '{print $$2}'`; do \ - if test "x$$buf" != "x"; then \ - echo $$buf \\ >>.depend ; \ - fi; \ - echo -n " " >>.depend ; \ - buf="$$d "; \ - done; \ - done; \ - if test "x$$buf" != "x"; then \ - echo $$buf >>.depend ; \ - fi; \ - echo "">> .shared ; \ - echo "">> .shared ; \ - echo -n $(LIB_NAME)_INCS = >> .shared ; \ - for f in $(LIB_INCS) config.h; do \ - echo " \\" >> .shared ; \ - echo -n ' $$('$(LIB_NAME)_PATH')'/$$f >> .shared ; \ - done; \ - echo "" >> .shared ; \ - (if test -d apps; then cd apps; $(MAKE) deps || exit 1; fi) - -apps: @APPSDEPS@ - @(if test -d apps; then cd apps; $(MAKE); fi ) - - -$(LIB_STATIC): $(LIB_OBJS) $(LIB_INCS) config.h - $(RMF) $(LIB_STATIC) - $(AR) $(LIB_STATIC) $(LIB_OBJS) - $(RANLIB) $(LIB_STATIC) - -test_asstorage.o: asstorage.c - $(CC) $(CCFLAGS) $(EXTRA_DEFINES) -DTEST_ASSTORAGE $(INCLUDES) $(EXTRA_INCLUDES) -c asstorage.c -o test_asstorage.o - -test_asstorage: test_asstorage.o - $(CC) test_asstorage.o $(USER_LD_FLAGS) $(LIBRARIES_TEST) $(EXTRA_LIBRARIES) -o test_asstorage - -test_asdraw.o: draw.c - $(CC) $(CCFLAGS) $(EXTRA_DEFINES) -DTEST_ASDRAW $(INCLUDES) $(EXTRA_INCLUDES) -c draw.c -o test_asdraw.o - -test_asdraw: test_asdraw.o - $(CC) test_asdraw.o $(USER_LD_FLAGS) $(LIBRARIES_TEST) $(EXTRA_LIBRARIES) -o test_asdraw - -test_mmx.o: test_mmx.c - $(CC) $(CCFLAGS) $(EXTRA_DEFINES) -DTEST_ASDRAW $(INCLUDES) $(EXTRA_INCLUDES) -c test_mmx.c -o test_mmx.o - -test_mmx: test_mmx.o - $(CC) test_mmx.o $(USER_LD_FLAGS) $(LIBRARIES_TEST) $(EXTRA_LIBRARIES) -o test_mmx - - -.c.o: - $(CC) $(CCFLAGS) $(EXTRA_DEFINES) $(INCLUDES) $(EXTRA_INCLUDES) -c $*.c -o $@ - -.c.s: - $(CC) $(CCFLAGS) $(EXTRA_DEFINES) $(INCLUDES) $(EXTRA_INCLUDES) -S $*.c - -# -# include dependency files if they exist -# -# this is merely a precaution, but as it does not work with ansi make -# we took it out -#ifneq ($(wildcard .depend),) -include .depend -#endif - -$(LIB_SHARED_CYG): $(LIB_OBJS) $(LIB_INCS) config.h - $(CC) -shared -o $(LIB_SHARED_CYG) \ - -Wl,--out-implib=$(LIB_SHARED_CYG_AR) \ - -Wl,--export-all-symbols -Wl,--enable-auto-import \ - -Wl,--whole-archive ${LIB_OBJS} \ - $(USER_LD_FLAGS) -Wl,--no-whole-archive $(LIBRARIES) - -$(LIB_SHARED): $(LIB_SHARED).$(LIBVERMAJOR) - $(LN_S) -f $(LIB_SHARED).$(LIBVERMAJOR) $(LIB_SHARED) - -$(LIB_SHARED).$(LIBVERMAJOR): $(LIB_SHARED).$(LIBVER) - $(LN_S) -f $(LIB_SHARED).$(LIBVER) $(LIB_SHARED).$(LIBVERMAJOR) - -$(LIB_SHARED).$(LIBVER): $(LIB_OBJS) $(LIB_INCS) config.h - $(CC) -shared $(USER_LD_FLAGS) -Wl,-soname,$(LIB_SHARED).$(LIBVERMAJOR) -o $(LIB_SHARED).$(LIBVER) \ - $(LIB_OBJS) $(LIBRARIES) - -install.man: - @if [ -d doc/man ] ; then \ - if [ ! -d $(AFTER_MAN_DIR) ] ; then $(MKDIR) -p $(AFTER_MAN_DIR); fi; \ - cd doc/man; \ - for f in `ls *.man`; do \ - page_name=`echo $$f| awk -F . '{print $$1}'`; \ - echo $(INSTALL_DATA) $$page_name.man $(AFTER_MAN_DIR)/$$page_name.3x; \ - $(INSTALL_DATA) $$page_name.man $(AFTER_MAN_DIR)/$$page_name.3x; \ - done; cd ../..; \ - fi - - -install.doc: - @if [ -d doc/html ] ; then \ - if [ ! -d $(AFTER_DOC_DIR)/html ] ; then $(MKDIR) -p $(AFTER_DOC_DIR)/html; fi; \ - cd doc/html; \ - for f in `ls *.html`; do \ - echo $(INSTALL_DATA) $$f $(AFTER_DOC_DIR)/html/$$f; \ - $(INSTALL_DATA) $$f $(AFTER_DOC_DIR)/html/$$f; \ - done; \ - cd ../..; \ - fi - -install: install.lib install.man install.doc install.apps - - -uninstall: uninstall.lib - diff --git a/graf2d/asimage/src/libAfterImage/README b/graf2d/asimage/src/libAfterImage/README deleted file mode 100644 index 65b144d4d749a..0000000000000 --- a/graf2d/asimage/src/libAfterImage/README +++ /dev/null @@ -1,30 +0,0 @@ -This directory contains libAfterImage core code. - -Here is how to build and install it : - -libAfterImage may utilize libAfterBase, for some of the low level -tasks, or it may run standalone, using its own subset of -libAfterBase. It is recommended to use libAfterBase whenever -possible, as it provides more functionality, and you may -actually utilize it in your programs for various tasks, such as -hash tables, file searching, etc. - -Both libraries can be built and installed by simply executing : - - ./configure ; make ; make install - -in respective directory. - -libAfterImage will install itself into /usr/local/lib on most -systems. In addition it will install afterimage-libs script to -/usr/local/bin. This script can be used to query what libraries -libAfterImage is dependant on. All of this libraries has to be -linked to, while building an application utilizing libAfterImage. -Header files for the library will be installed into -/usr/local/include/libAfterImage on most systems. - -Check out API documentation and example apps. - -Thanks for using libAfterImage. Contributions and bug reports are -always welcome. Please e-mail yours to , -or any of the AfterStep mailing lists. diff --git a/graf2d/asimage/src/libAfterImage/aclocal.m4 b/graf2d/asimage/src/libAfterImage/aclocal.m4 deleted file mode 100644 index aef4c8b18c1aa..0000000000000 --- a/graf2d/asimage/src/libAfterImage/aclocal.m4 +++ /dev/null @@ -1,988 +0,0 @@ -dnl aclocal.m4 generated automatically by aclocal 1.4-p6 - -dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl This program is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without -dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A -dnl PARTICULAR PURPOSE. - -# lib-prefix.m4 serial 4 (gettext-0.14.2) -dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl From Bruno Haible. - -dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and -dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't -dnl require excessive bracketing. -ifdef([AC_HELP_STRING], -[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], -[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) - -dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed -dnl to access previously installed libraries. The basic assumption is that -dnl a user will want packages to use other packages they previously installed -dnl with the same --prefix option. -dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate -dnl libraries, but is otherwise very convenient. -AC_DEFUN([AC_LIB_PREFIX], -[ - AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) - AC_REQUIRE([AC_PROG_CC]) - AC_REQUIRE([AC_CANONICAL_HOST]) - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - dnl By default, look in $includedir and $libdir. - use_additional=yes - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - AC_LIB_ARG_WITH([lib-prefix], -[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib - --without-lib-prefix don't search for libraries in includedir and libdir], -[ - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - else - additional_includedir="$withval/include" - additional_libdir="$withval/lib" - fi - fi -]) - if test $use_additional = yes; then - dnl Potentially add $additional_includedir to $CPPFLAGS. - dnl But don't add it - dnl 1. if it's the standard /usr/include, - dnl 2. if it's already present in $CPPFLAGS, - dnl 3. if it's /usr/local/include and we are using GCC on Linux, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - for x in $CPPFLAGS; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - dnl Really add $additional_includedir to $CPPFLAGS. - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" - fi - fi - fi - fi - dnl Potentially add $additional_libdir to $LDFLAGS. - dnl But don't add it - dnl 1. if it's the standard /usr/lib, - dnl 2. if it's already present in $LDFLAGS, - dnl 3. if it's /usr/local/lib and we are using GCC on Linux, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_libdir" != "X/usr/lib"; then - haveit= - for x in $LDFLAGS; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test "X$additional_libdir" = "X/usr/local/lib"; then - if test -n "$GCC"; then - case $host_os in - linux*) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - dnl Really add $additional_libdir to $LDFLAGS. - LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" - fi - fi - fi - fi - fi -]) - -dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, -dnl acl_final_exec_prefix, containing the values to which $prefix and -dnl $exec_prefix will expand at the end of the configure script. -AC_DEFUN([AC_LIB_PREPARE_PREFIX], -[ - dnl Unfortunately, prefix and exec_prefix get only finally determined - dnl at the end of configure. - if test "X$prefix" = "XNONE"; then - acl_final_prefix="$ac_default_prefix" - else - acl_final_prefix="$prefix" - fi - if test "X$exec_prefix" = "XNONE"; then - acl_final_exec_prefix='${prefix}' - else - acl_final_exec_prefix="$exec_prefix" - fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" - prefix="$acl_save_prefix" -]) - -dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the -dnl variables prefix and exec_prefix bound to the values they will have -dnl at the end of the configure script. -AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], -[ - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - $1 - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" -]) - -# lib-link.m4 serial 6 (gettext-0.14.3) -dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl From Bruno Haible. - -AC_PREREQ(2.50) - -dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and -dnl the libraries corresponding to explicit and implicit dependencies. -dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and -dnl augments the CPPFLAGS variable. -AC_DEFUN([AC_LIB_LINKFLAGS], -[ - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - AC_REQUIRE([AC_LIB_RPATH]) - define([Name],[translit([$1],[./-], [___])]) - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) - AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ - AC_LIB_LINKFLAGS_BODY([$1], [$2]) - ac_cv_lib[]Name[]_libs="$LIB[]NAME" - ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" - ac_cv_lib[]Name[]_cppflags="$INC[]NAME" - ]) - LIB[]NAME="$ac_cv_lib[]Name[]_libs" - LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" - INC[]NAME="$ac_cv_lib[]Name[]_cppflags" - AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) - AC_SUBST([LIB]NAME) - AC_SUBST([LTLIB]NAME) - dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the - dnl results of this search when this library appears as a dependency. - HAVE_LIB[]NAME=yes - undefine([Name]) - undefine([NAME]) -]) - -dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) -dnl searches for libname and the libraries corresponding to explicit and -dnl implicit dependencies, together with the specified include files and -dnl the ability to compile and link the specified testcode. If found, it -dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and -dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and -dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs -dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. -AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], -[ - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - AC_REQUIRE([AC_LIB_RPATH]) - define([Name],[translit([$1],[./-], [___])]) - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) - - dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME - dnl accordingly. - AC_LIB_LINKFLAGS_BODY([$1], [$2]) - - dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, - dnl because if the user has installed lib[]Name and not disabled its use - dnl via --without-lib[]Name-prefix, they want to use it. - ac_save_CPPFLAGS="$CPPFLAGS" - AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) - - AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ - ac_save_LIBS="$LIBS" - LIBS="$LIBS $LIB[]NAME" - AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) - LIBS="$ac_save_LIBS" - ]) - if test "$ac_cv_lib[]Name" = yes; then - HAVE_LIB[]NAME=yes - AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) - AC_MSG_CHECKING([how to link with lib[]$1]) - AC_MSG_RESULT([$LIB[]NAME]) - else - HAVE_LIB[]NAME=no - dnl If $LIB[]NAME didn't lead to a usable library, we don't need - dnl $INC[]NAME either. - CPPFLAGS="$ac_save_CPPFLAGS" - LIB[]NAME= - LTLIB[]NAME= - fi - AC_SUBST([HAVE_LIB]NAME) - AC_SUBST([LIB]NAME) - AC_SUBST([LTLIB]NAME) - undefine([Name]) - undefine([NAME]) -]) - -dnl Determine the platform dependent parameters needed to use rpath: -dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, -dnl hardcode_direct, hardcode_minus_L. -AC_DEFUN([AC_LIB_RPATH], -[ - dnl Tell automake >= 1.10 to complain if config.rpath is missing. - m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) - AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS - AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld - AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host - AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir - AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ - CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ - ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh - . ./conftest.sh - rm -f ./conftest.sh - acl_cv_rpath=done - ]) - wl="$acl_cv_wl" - libext="$acl_cv_libext" - shlibext="$acl_cv_shlibext" - hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" - hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" - hardcode_direct="$acl_cv_hardcode_direct" - hardcode_minus_L="$acl_cv_hardcode_minus_L" - dnl Determine whether the user wants rpath handling at all. - AC_ARG_ENABLE(rpath, - [ --disable-rpath do not hardcode runtime library paths], - :, enable_rpath=yes) -]) - -dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and -dnl the libraries corresponding to explicit and implicit dependencies. -dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. -AC_DEFUN([AC_LIB_LINKFLAGS_BODY], -[ - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) - dnl By default, look in $includedir and $libdir. - use_additional=yes - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - AC_LIB_ARG_WITH([lib$1-prefix], -[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib - --without-lib$1-prefix don't search for lib$1 in includedir and libdir], -[ - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - else - additional_includedir="$withval/include" - additional_libdir="$withval/lib" - fi - fi -]) - dnl Search the library and its dependencies in $additional_libdir and - dnl $LDFLAGS. Using breadth-first-seach. - LIB[]NAME= - LTLIB[]NAME= - INC[]NAME= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='$1 $2' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - dnl See if it was already located by an earlier AC_LIB_LINKFLAGS - dnl or AC_LIB_HAVE_LINKFLAGS call. - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" - else - dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined - dnl that this library doesn't exist. So just drop it. - : - fi - else - dnl Search the library lib$name in $additional_libdir and $LDFLAGS - dnl and the already constructed $LIBNAME/$LTLIBNAME. - found_dir= - found_la= - found_so= - found_a= - if test $use_additional = yes; then - if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then - found_dir="$additional_libdir" - found_so="$additional_libdir/lib$name.$shlibext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - else - if test -f "$additional_libdir/lib$name.$libext"; then - found_dir="$additional_libdir" - found_a="$additional_libdir/lib$name.$libext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then - found_dir="$dir" - found_so="$dir/lib$name.$shlibext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - else - if test -f "$dir/lib$name.$libext"; then - found_dir="$dir" - found_a="$dir/lib$name.$libext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - fi - fi - ;; - esac - if test "X$found_dir" != "X"; then - break - fi - done - fi - if test "X$found_dir" != "X"; then - dnl Found the library. - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" - if test "X$found_so" != "X"; then - dnl Linking with a shared library. We attempt to hardcode its - dnl directory into the executable's runpath, unless it's the - dnl standard /usr/lib. - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then - dnl No hardcoding is needed. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - else - dnl Use an explicit option to hardcode DIR into the resulting - dnl binary. - dnl Potentially add DIR to ltrpathdirs. - dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $found_dir" - fi - dnl The hardcoding into $LIBNAME is system dependent. - if test "$hardcode_direct" = yes; then - dnl Using DIR/libNAME.so during linking hardcodes DIR into the - dnl resulting binary. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - else - if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then - dnl Use an explicit option to hardcode DIR into the resulting - dnl binary. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - dnl Potentially add DIR to rpathdirs. - dnl The rpathdirs will be appended to $LIBNAME at the end. - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" - fi - else - dnl Rely on "-L$found_dir". - dnl But don't add it if it's already contained in the LDFLAGS - dnl or the already constructed $LIBNAME - haveit= - for x in $LDFLAGS $LIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" - fi - if test "$hardcode_minus_L" != no; then - dnl FIXME: Not sure whether we should use - dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" - dnl here. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - else - dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH - dnl here, because this doesn't fit in flags passed to the - dnl compiler. So give up. No hardcoding. This affects only - dnl very old systems. - dnl FIXME: Not sure whether we should use - dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" - dnl here. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - dnl Linking with a static library. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" - else - dnl We shouldn't come here, but anyway it's good to have a - dnl fallback. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" - fi - fi - dnl Assume the include files are nearby. - additional_includedir= - case "$found_dir" in - */lib | */lib/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - dnl Potentially add $additional_includedir to $INCNAME. - dnl But don't add it - dnl 1. if it's the standard /usr/include, - dnl 2. if it's /usr/local/include and we are using GCC on Linux, - dnl 3. if it's already present in $CPPFLAGS or the already - dnl constructed $INCNAME, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INC[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - dnl Really add $additional_includedir to $INCNAME. - INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - dnl Look for dependencies. - if test -n "$found_la"; then - dnl Read the .la file. It defines the variables - dnl dlname, library_names, old_library, dependency_libs, current, - dnl age, revision, installed, dlopen, dlpreopen, libdir. - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - dnl We use only dependency_libs. - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. - dnl But don't add it - dnl 1. if it's the standard /usr/lib, - dnl 2. if it's /usr/local/lib and we are using GCC on Linux, - dnl 3. if it's already present in $LDFLAGS or the already - dnl constructed $LIBNAME, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_libdir" != "X/usr/lib"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/lib"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - dnl Really add $additional_libdir to $LIBNAME. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - dnl Really add $additional_libdir to $LTLIBNAME. - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - dnl Potentially add DIR to rpathdirs. - dnl The rpathdirs will be appended to $LIBNAME at the end. - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - dnl Potentially add DIR to ltrpathdirs. - dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - dnl Handle this in the next round. - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - dnl Handle this in the next round. Throw away the .la's - dnl directory; it is already contained in a preceding -L - dnl option. - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - dnl Most likely an immediate library name. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" - ;; - esac - done - fi - else - dnl Didn't find the library; assume it is in the system directories - dnl known to the linker and runtime loader. (All the system - dnl directories known to the linker should also be known to the - dnl runtime loader, otherwise the system is severely misconfigured.) - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$hardcode_libdir_separator"; then - dnl Weird platform: only the last -rpath option counts, the user must - dnl pass all path elements in one option. We can arrange that for a - dnl single library, but not when more than one $LIBNAMEs are used. - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" - done - dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" - else - dnl The -rpath options are cumulative. - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - dnl When using libtool, the option that works for both libraries and - dnl executables is -R. The -R options are cumulative. - for found_dir in $ltrpathdirs; do - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" - done - fi -]) - -dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, -dnl unless already present in VAR. -dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes -dnl contains two or three consecutive elements that belong together. -AC_DEFUN([AC_LIB_APPENDTOVAR], -[ - for element in [$2]; do - haveit= - for x in $[$1]; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - [$1]="${[$1]}${[$1]:+ }$element" - fi - done -]) - -# lib-ld.m4 serial 3 (gettext-0.13) -dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl Subroutines of libtool.m4, -dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision -dnl with libtool.m4. - -dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. -AC_DEFUN([AC_LIB_PROG_LD_GNU], -[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, -[# I'd rather use --version here, but apparently some GNU ld's only accept -v. -case `$LD -v 2>&1 conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by GCC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]* | [A-Za-z]:[\\/]*)] - [re_direlt='/[^/][^/]*/\.\./'] - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(acl_cv_path_LD, -[if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - acl_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in - *GNU* | *'with BFD'*) - test "$with_gnu_ld" != no && break ;; - *) - test "$with_gnu_ld" != yes && break ;; - esac - fi - done - IFS="$ac_save_ifs" -else - acl_cv_path_LD="$LD" # Let the user override the test with a path. -fi]) -LD="$acl_cv_path_LD" -if test -n "$LD"; then - AC_MSG_RESULT($LD) -else - AC_MSG_RESULT(no) -fi -test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) -AC_LIB_PROG_LD_GNU -]) - -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# -# Copyright © 2004 Scott James Remnant . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- -AC_DEFUN([PKG_PROG_PKG_CONFIG], -[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) -AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=m4_default([$1], [0.9.0]) - AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - PKG_CONFIG="" - fi - -fi[]dnl -])# PKG_PROG_PKG_CONFIG - -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# -# Similar to PKG_CHECK_MODULES, make sure that the first instance of -# this or PKG_CHECK_MODULES is called, or make sure to call -# PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- -AC_DEFUN([PKG_CHECK_EXISTS], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -if test -n "$PKG_CONFIG" && \ - AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then - m4_ifval([$2], [$2], [:]) -m4_ifvaln([$3], [else - $3])dnl -fi]) - - -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- -m4_define([_PKG_CONFIG], -[if test -n "$PKG_CONFIG"; then - if test -n "$$1"; then - pkg_cv_[]$1="$$1" - else - PKG_CHECK_EXISTS([$3], - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], - [pkg_failed=yes]) - fi -else - pkg_failed=untried -fi[]dnl -])# _PKG_CONFIG - -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- -AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED - - -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- -AC_DEFUN([PKG_CHECK_MODULES], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl -AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl - -pkg_failed=no -AC_MSG_CHECKING([for $1]) - -_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) -_PKG_CONFIG([$1][_LIBS], [libs], [$2]) - -m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS -and $1[]_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details.]) - -if test $pkg_failed = yes; then - _PKG_SHORT_ERRORS_SUPPORTED - if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` - else - $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` - fi - # Put the nasty error message in config.log where it belongs - echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD - - ifelse([$4], , [AC_MSG_ERROR(dnl -[Package requirements ($2) were not met: - -$$1_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -_PKG_TEXT -])], - [$4]) -elif test $pkg_failed = untried; then - ifelse([$4], , [AC_MSG_FAILURE(dnl -[The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -_PKG_TEXT - -To get pkg-config, see .])], - [$4]) -else - $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS - $1[]_LIBS=$pkg_cv_[]$1[]_LIBS - AC_MSG_RESULT([yes]) - ifelse([$3], , :, [$3]) -fi[]dnl -])# PKG_CHECK_MODULES - diff --git a/graf2d/asimage/src/libAfterImage/afterbase.c b/graf2d/asimage/src/libAfterImage/afterbase.c index 3f21a0e332ef5..0456fd9b23cfc 100644 --- a/graf2d/asimage/src/libAfterImage/afterbase.c +++ b/graf2d/asimage/src/libAfterImage/afterbase.c @@ -15,11 +15,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif #include #include @@ -66,11 +61,9 @@ #ifdef _WIN32 #include #include -#include "win32/afterbase.h" #define access _access -#else -#include "afterbase.h" #endif +#include "afterbase.h" #include "asimage.h" #ifdef X_DISPLAY_MISSING @@ -193,7 +186,9 @@ void asim_nonGNUC_debugout( const char *format, ...) } void asim_nonGNUC_debugout_stub( const char *format, ...) -{} +{ + (void)format; // silence unused variable warning +} /* from libAfterBase/fs.c : */ @@ -201,8 +196,8 @@ int asim_check_file_mode (const char *file, int mode) { struct stat st; - if ((stat (file, &st) == -1) || (st.st_mode & S_IFMT) != mode) - return (-1); + if ((stat(file, &st) == -1) || (int)(st.st_mode & S_IFMT) != mode) + return (-1); else return (0); } @@ -541,9 +536,8 @@ asim_mystrncasecmp (const char *s1, const char *s2, size_t n) if (s1 == NULL || s2 == NULL) return (s1 == s2) ? 0 : ((s1==NULL)?1:-1); - while( i < n ) - { - c1 = s1[i], c2 = s2[i]; + while ((size_t)i < n) { + c1 = s1[i], c2 = s2[i]; ++i ; if (c1==0) return -c2; @@ -553,8 +547,8 @@ asim_mystrncasecmp (const char *s1, const char *s2, size_t n) c2 = tolower(c2); if (c1 != c2) return (c1 - c2); - } - return 0; + } + return 0; } #ifdef X_DISPLAY_MISSING @@ -631,28 +625,28 @@ const char *asim_parse_argb_color( const char *color, CARD32 *pargb ) } }else if( *color ) { - /* does not really matter here what screen to use : */ - Display *dpy = get_default_asvisual()->dpy; #ifdef X_DISPLAY_MISSING register const char *ptr = &(color[0]); if(!FindColor(color, pargb)) return color; - while( !isspace((int)*ptr) && *ptr != '\0' ) ptr++; - return ptr; + while (!isspace((int)*ptr) && *ptr != '\0') + ptr++; + return ptr; #else - if( dpy == NULL ) + /* does not really matter here what screen to use : */ + Display *dpy = get_default_asvisual()->dpy; + if( dpy == NULL ) return color ; else { - register const char *ptr = &(color[0]); -#ifndef X_DISPLAY_MISSING - XColor xcol, xcol_scr ; + register const char *ptr = &(color[0]); + XColor xcol, xcol_scr ; /* XXX Not sure if Scr.asv->colormap is always defined here. If not, ** change back to DefaultColormap(dpy,DefaultScreen(dpy)). */ if( XLookupColor( dpy, DefaultColormap(dpy,DefaultScreen(dpy)), color, &xcol, &xcol_scr) ) - *pargb = 0xFF000000|((xcol.red<<8)&0x00FF0000)|(xcol.green&0x0000FF00)|((xcol.blue>>8)&0x000000FF); -#endif - while( !isspace((int)*ptr) && *ptr != '\0' ) ptr++; + *pargb = 0xFF000000 | ((xcol.red << 8) & 0x00FF0000) | (xcol.green & 0x0000FF00) | + ((xcol.blue >> 8) & 0x000000FF); + while( !isspace((int)*ptr) && *ptr != '\0' ) ptr++; return ptr; } #endif @@ -870,10 +864,10 @@ asim_add_hash_item (ASHashTable * hash, ASHashableValue value, void *data) if (key >= hash->size) return ASH_BadParameter; - if( deallocated_used > 0 ) - item = deallocated_mem[--deallocated_used]; - else - item = safecalloc (1, sizeof (ASHashItem)); + if (deallocated_used > 0) + item = deallocated_mem[--deallocated_used]; + else + item = safecalloc(1, sizeof(ASHashItem)); item->next = NULL; item->value = value; @@ -1018,8 +1012,8 @@ asim_string_hash_value (ASHashableValue value, ASHashKey hash_size) break; hash_key += (((ASHashKey) c) << i); ++i ; - }while( i < ((sizeof (ASHashKey) - sizeof (char)) << 3) ); - return hash_key % hash_size; + } while ((size_t)i < ((sizeof(ASHashKey) - sizeof(char)) << 3)); + return hash_key % hash_size; } long @@ -1047,7 +1041,8 @@ asim_string_compare (ASHashableValue value1, ASHashableValue value2) void asim_string_destroy_without_data (ASHashableValue value, void *data) { - if ((char*)value != NULL) + (void)data; // silence unused variable warning + if ((char*)value != NULL) free ((char*)value); } @@ -1069,9 +1064,9 @@ asim_casestring_hash_value (ASHashableValue value, ASHashKey hash_size) c = tolower (c); hash_key += (((ASHashKey) c) << i); ++i; - }while(i < ((sizeof (ASHashKey) - sizeof (char)) << 3)); + } while ((size_t)i < ((sizeof(ASHashKey) - sizeof(char)) << 3)); - return hash_key % hash_size; + return hash_key % hash_size; } long @@ -1118,6 +1113,9 @@ asim_get_drawable_size (Drawable d, unsigned int *ret_w, unsigned int *ret_h) if (XGetGeometry (dpy, d, &root, &junk, &junk, ret_w, ret_h, &ujunk, &ujunk) != 0) return 1; } +#else + (void)d; + (void)dpy; // silence unused variable warning #endif return 0; } @@ -1127,15 +1125,53 @@ int XParseGeometry ( char *string,int *x,int *y, unsigned int *width, /* RETURN */ unsigned int *height) /* RETURN */ { - show_error( "Parsing of geometry is not supported without either Xlib opr libAfterBase" ); - return 0; + (void)string; + (void)x; + (void)y; + (void)width; + (void)height; // silence unused variable warning + show_error("Parsing of geometry is not supported without either Xlib or libAfterBase"); + return 0; +} +void XDestroyImage(void *d) +{ + (void)d; // silence unused variable warning +} +int XGetWindowAttributes(void *d, Window w, unsigned long m, void *s) +{ + (void)d; + (void)w; + (void)m; + (void)s; // silence unused variable warning + return 0; } -void XDestroyImage( void* d){} -int XGetWindowAttributes( void*d, Window w, unsigned long m, void* s){ return 0;} void *XGetImage( void* dpy,Drawable d,int x,int y,unsigned int width,unsigned int height, unsigned long m,int t) -{return NULL ;} -unsigned long XGetPixel(void* d, int x, int y){return 0;} -int XQueryColors(void* a,Colormap c,void* x,int m){return 0;} +{ + (void)dpy; + (void)d; + (void)x; + (void)y; + (void)width; + (void)height; + (void)m; + (void)t; // silence unused variable warning + return NULL; +} +unsigned long XGetPixel(void *d, int x, int y) +{ + (void)d; + (void)x; + (void)y; // silence unused variable warning + return 0; +} +int XQueryColors(void *a, Colormap c, void *x, int m) +{ + (void)a; + (void)c; + (void)x; + (void)m; // silence unused variable warning + return 0; +} #endif @@ -1310,16 +1346,14 @@ asim_asxml_var_init(void) { if ( asxml_var == NULL ) { - Display *dpy = get_default_asvisual()->dpy; - - asxml_var = create_ashash(0, string_hash_value, string_compare, string_destroy_without_data); - if (!asxml_var) return; + asxml_var = create_ashash(0, string_hash_value, string_compare, string_destroy_without_data); + if (!asxml_var) return; #ifndef X_DISPLAY_MISSING - if ( dpy != NULL ) - { - asxml_var_insert("xroot.width", XDisplayWidth (dpy, DefaultScreen(dpy))); + Display *dpy = get_default_asvisual()->dpy; + if (dpy != NULL) { + asxml_var_insert("xroot.width", XDisplayWidth (dpy, DefaultScreen(dpy))); asxml_var_insert("xroot.height", XDisplayHeight(dpy, DefaultScreen(dpy))); - } + } #endif } } @@ -1538,9 +1572,9 @@ int asim_xml_parse(const char* str, xml_elem_t* current, ASHashTable *vocabulary /* Find a tag of the form , , or . */ while (*ptr) { - const char* oab = ptr; + const char *oab; - /* Look for an open oab bracket. */ + /* Look for an open oab bracket. */ for (oab = ptr ; *oab && *oab != '<' ; oab++); /* If there are no oab brackets left, we're done. */ diff --git a/graf2d/asimage/src/libAfterImage/afterbase.h b/graf2d/asimage/src/libAfterImage/afterbase.h index 37a2314dc9ab9..9f6fe282f2ccf 100644 --- a/graf2d/asimage/src/libAfterImage/afterbase.h +++ b/graf2d/asimage/src/libAfterImage/afterbase.h @@ -1,41 +1,11 @@ #ifndef AFTERBASE_H_HEADER_INCLUDED #define AFTERBASE_H_HEADER_INCLUDED -#define HAVE_AFTERBASE_FLAG 0 +#include "asim_afterbase.h" -#if 0 -# if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -# else -#include "libAfterBase/astypes.h" -#include "libAfterBase/audit.h" -#include "libAfterBase/output.h" -#include "libAfterBase/safemalloc.h" -#include "libAfterBase/mystring.h" -#include "libAfterBase/fs.h" -#include "libAfterBase/parse.h" -#include "libAfterBase/selfdiag.h" -#include "libAfterBase/sleep.h" -#include "libAfterBase/socket.h" -#include "libAfterBase/trace.h" -#include "libAfterBase/xml.h" -# endif -#else - -# include "asim_afterbase.h" - -#endif /* HAVE_AFTERBASE */ +#ifdef _WIN32 +#define R_OK 04 +#endif #endif /* AFTERBASE_H_HEADER_INCLUDED */ diff --git a/graf2d/asimage/src/libAfterImage/afterbase.h.in b/graf2d/asimage/src/libAfterImage/afterbase.h.in deleted file mode 100644 index 2333f79170c9a..0000000000000 --- a/graf2d/asimage/src/libAfterImage/afterbase.h.in +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef AFTERBASE_H_HEADER_INCLUDED -#define AFTERBASE_H_HEADER_INCLUDED - -#define HAVE_AFTERBASE_FLAG @HAVE_AFTERBASE_FLAG@ - -#if @HAVE_AFTERBASE_FLAG@ -# if @USE_DEFAULT_AFTERBASE@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -# else -#include "@AFTERBASE_INCS_PATH@libAfterBase/astypes.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/audit.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/output.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/safemalloc.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/mystring.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/fs.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/parse.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/selfdiag.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/sleep.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/socket.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/trace.h" -#include "@AFTERBASE_INCS_PATH@libAfterBase/xml.h" -# endif -#else - -# include "asim_afterbase.h" - -#endif /* HAVE_AFTERBASE */ - -#endif /* AFTERBASE_H_HEADER_INCLUDED */ - diff --git a/graf2d/asimage/src/libAfterImage/afterimage-config.in b/graf2d/asimage/src/libAfterImage/afterimage-config.in deleted file mode 100644 index 00c4e5ea2f854..0000000000000 --- a/graf2d/asimage/src/libAfterImage/afterimage-config.in +++ /dev/null @@ -1,141 +0,0 @@ -#! /bin/sh - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -AFTERIMAGE_LIBS="@AFTERIMAGE_LIBS@" -AFTERIMAGE_LIBS_EXTERNAL="@AFTERIMAGE_LIBS_EXTERNAL@" -HAVE_AFTERBASE="@have_afterbase@" -AFTERIMAGE_PREF_FORMAT="@image_format@" -AFTERIMAGE_X_SUPPORT="@afterimage_x_support@" - - -usage() -{ - cat <&2 -fi - -while test $# -gt 0 ; do - case "$1" in - -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - case $1 in - --prefix=*) - prefix=$optarg - local_prefix=yes - ;; - --prefix) - echo_prefix=yes - ;; - --exec-prefix=*) - exec_prefix=$optarg - exec_prefix_set=yes - local_prefix=yes - ;; - --exec-prefix) - echo_exec_prefix=yes - ;; - --version) - echo @version@ - exit 0 - ;; - --cflags) - echo_cflags=yes - ;; - --libs) - echo_libs=yes - ;; - --libtool) - echo_libtool=yes - ;; - --have-afterbase) - echo_have_afterbase=yes - ;; - --have-x-support) - echo_have_x_support=yes - ;; - --preferred-image-format) - echo_preferred_image_format=yes - ;; - --external-only) - echo_external_only=yes - ;; - *) - usage 1 1>&2 - ;; - esac - shift -done - -if test "$local_prefix" = "yes" ; then - if test "$exec_prefix_set" != "yes" ; then - exec_prefix=$prefix - fi -fi - -if test "$echo_prefix" = "yes" ; then - echo $prefix -fi - -if test "$echo_exec_prefix" = "yes" ; then - echo $exec_prefix -fi - -if test "$echo_cflags" = "yes" ; then - cflags="-I@includedir@/libAfterImage" - if test "@includedir@" != "/usr/include" ; then - echo $cflags -I@includedir@ - else - echo $cflags - fi -fi - -if test "$echo_libs" = "yes" ; then - libs="$AFTERIMAGE_LIBS_EXTERNAL" - if test "$echo_external_only" != "yes"; then - if test "@have_afterbase@" = "yes" ; then - libs="-lAfterBase $libs" - fi - libs="-lAfterImage $libs" - echo $libs - else - echo $libs - fi -fi - -if test "$echo_libtool" = "yes" ; then - convlib="libAfterImage.la" - echo @libdir@/$convlib -fi - -if test "$echo_have_afterbase" = "yes" ; then - echo "@have_afterbase@" -fi - -if test "$echo_have_x_support" = "yes" ; then - echo "@afterimage_x_support@" -fi - -if test "$echo_preferred_image_format" = "yes" ; then - echo "@image_format@" -fi - -# EOF diff --git a/graf2d/asimage/src/libAfterImage/afterimage-libs.in b/graf2d/asimage/src/libAfterImage/afterimage-libs.in deleted file mode 100644 index 20f7851f04277..0000000000000 --- a/graf2d/asimage/src/libAfterImage/afterimage-libs.in +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/sh -# - -AFTERIMAGE_LIBS="@AFTERIMAGE_LIBS@" -AFTERIMAGE_LIBS_EXTERNAL="@AFTERIMAGE_LIBS_EXTERNAL@" -HAVE_AFTERBASE="@have_afterbase@" -AFTERIMAGE_PREF_FORMAT="@image_format@" - -export AFTERIMAGE_LIBS -export AFTERIMAGE_LIBS_EXTERNAL -export HAVE_AFTERBASE -export AFTERIMAGE_PREF_FORMAT - -if test "x$1" = "x--external-only" ; then - echo $AFTERIMAGE_LIBS_EXTERNAL -else - if test "x$1" = "x--have-afterbase" ; then - echo $HAVE_AFTERBASE - else - if test "x$1" = "x--preferred-image-format" ; then - echo $AFTERIMAGE_PREF_FORMAT - else - echo $AFTERIMAGE_LIBS - fi - fi -fi -exit 0 diff --git a/graf2d/asimage/src/libAfterImage/afterimage.h b/graf2d/asimage/src/libAfterImage/afterimage.h index 25c6e137000fa..b8b849509a041 100644 --- a/graf2d/asimage/src/libAfterImage/afterimage.h +++ b/graf2d/asimage/src/libAfterImage/afterimage.h @@ -150,20 +150,6 @@ * AUTHOR * Sasha Vasko *********/ -/****h* libAfterImage/Examples - * EXAMPLE - * ASView - image loading from the file and displaying in window. - * ASScale - image loading from file and scaling to arbitrary size. - * ASTile - image loading from file, tiling and tinting to arbitrary - * size and color. - * ASMerge - imgae loading and merging with another image. - * ASGrad - mutlipoint gradient drawing. - * ASFlip - image loading from file and rotation. - * ASText - trexturized semitransparent antialised text drawing. - * - * SEE ALSO - * API Reference - ******/ /****h* libAfterImage/API Reference * CHILDREN * Headers : diff --git a/graf2d/asimage/src/libAfterImage/afterrootpngwrite.c b/graf2d/asimage/src/libAfterImage/afterrootpngwrite.c index 0ed1ed96f5f54..530acde5feb44 100644 --- a/graf2d/asimage/src/libAfterImage/afterrootpngwrite.c +++ b/graf2d/asimage/src/libAfterImage/afterrootpngwrite.c @@ -1,9 +1,3 @@ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #include "afterrootpngwrite.h" # ifdef HAVE_BUILTIN_PNG diff --git a/graf2d/asimage/src/libAfterImage/ascmap.c b/graf2d/asimage/src/libAfterImage/ascmap.c index de993b59c5e95..6e0261fbf609b 100644 --- a/graf2d/asimage/src/libAfterImage/ascmap.c +++ b/graf2d/asimage/src/libAfterImage/ascmap.c @@ -22,12 +22,6 @@ #undef LOCAL_DEBUG #undef DO_CLOCKING -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #include #if TIME_WITH_SYS_TIME # include @@ -50,11 +44,7 @@ #endif #include -#ifdef _WIN32 -# include "win32/afterbase.h" -#else # include "afterbase.h" -#endif #include "asimage.h" #include "import.h" @@ -432,25 +422,20 @@ print_asimage( im, ASFLAGS_EVERYTHING, __FUNCTION__, __LINE__ ); if( max_colors == 0 ) max_colors = 256 ; - if( dither == -1 ) - dither = 4 ; - else if( dither >= 8 ) - dither = 7 ; - switch( dither ) - { - case 0 : - case 1 : - case 2 : buckets_num = 4096 ; - break ; - case 3 : - case 4 : buckets_num = 1024 ; - break ; - case 5 : - case 6 : buckets_num = 64 ; - break ; - case 7 : buckets_num = 8 ; - break ; - } + if (dither == (unsigned int)-1) + dither = 4; + else if (dither >= 8) + dither = 7; + switch (dither) { + case 0: + case 1: + case 2: buckets_num = 4096; break; + case 3: + case 4: buckets_num = 1024; break; + case 5: + case 6: buckets_num = 64; break; + case 7: buckets_num = 8; break; + } dst = mapped_im = safemalloc( im->width*im->height*sizeof(int)); memset(cmap, 0x00, sizeof(ASColormap)); diff --git a/graf2d/asimage/src/libAfterImage/asfont.c b/graf2d/asimage/src/libAfterImage/asfont.c index 415bf6147686b..a673b29c0e9e1 100644 --- a/graf2d/asimage/src/libAfterImage/asfont.c +++ b/graf2d/asimage/src/libAfterImage/asfont.c @@ -18,13 +18,6 @@ #undef LOCAL_DEBUG #undef DO_CLOCKING -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - - #define DO_X11_ANTIALIASING #define DO_2STEP_X11_ANTIALIASING #define DO_3STEP_X11_ANTIALIASING @@ -75,11 +68,7 @@ #define INCLUDE_ASFONT_PRIVATE -#ifdef _WIN32 -# include "win32/afterbase.h" -#else # include "afterbase.h" -#endif #include "asfont.h" #include "asimage.h" #include "asvisual.h" @@ -272,6 +261,10 @@ open_X11_font_int( ASFontManager *fontman, const char *font_string, ASFlagType f font->flags = flags ; load_X11_glyphs( fontman->dpy, font, xfs ); XFreeFont( fontman->dpy, xfs ); +#else + (void)fontman; + (void)font_string; + (void)flags; // silence unused variable warning #endif /* #ifndef X_DISPLAY_MISSING */ return font; } @@ -428,7 +421,8 @@ destroy_font( ASFont *font ) void asglyph_destroy (ASHashableValue value, void *data) { - if( data ) + (void)value; // silence unused variable warning) + if( data ) { free_glyph_data( (ASGlyph*)data ); free( data ); @@ -809,9 +803,8 @@ LOCAL_DEBUG_OUT( "loading glyph range of %lu-%lu", r->min_char, r->max_char ); if( chars[i].lbearing > 0 ) pen_x += chars[i].lbearing ; - for( y = 0 ; y < height ; y++ ) - { - for( x = 0 ; x < width ; x++ ) + for (y = 0; y < (int)height; y++) { + for( x = 0 ; x < width ; x++ ) { /* fprintf( stderr, "glyph %d (%c): (%d,%d) 0x%X\n", i, (char)(i+r->min_char), x, y, XGetPixel( xim, pen_x+x, y ));*/ /* remember default GC colors are black on white - 0 on 1 - and we need @@ -819,7 +812,7 @@ LOCAL_DEBUG_OUT( "loading glyph range of %lu-%lu", r->min_char, r->max_char ); row[x] = ( XGetPixel( xim, pen_x+x, y ) != 0 )? 0x00:0xFF; } row += width; - } + } #ifdef DO_X11_ANTIALIASING if( height > X11_AA_HEIGHT_THRESHOLD ) @@ -1091,21 +1084,19 @@ load_glyph_freetype( ASFont *font, ASGlyph *asg, int glyph, UNICODE_CHAR uc ) register CARD8 *buf ; int i ; asg->width = (int)font->space_size - asg->lead ; - if( glyph_scaling_buf_size < bmap->width*bmap->rows*2 ) - { - glyph_scaling_buf_size = bmap->width*bmap->rows*2; + if ((unsigned int)glyph_scaling_buf_size < bmap->width * bmap->rows * 2) { + glyph_scaling_buf_size = bmap->width*bmap->rows*2; glyph_scaling_buf = realloc( glyph_scaling_buf, glyph_scaling_buf_size ); - } - buf = &(glyph_scaling_buf[0]); - for( i = 0 ; i < bmap->rows ; ++i ) - { - int k = bmap->width; + } + buf = &(glyph_scaling_buf[0]); + for (i = 0; i < (int)bmap->rows; ++i) { + int k = bmap->width; while( --k >= 0 ) buf[k] = src[k] ; buf += bmap->width ; - src += src_step ; - } - src = &(glyph_scaling_buf[0]); + src += src_step ; + } + src = &(glyph_scaling_buf[0]); scale_down_glyph_width( src, bmap->width, asg->width, asg->height ); src_step = asg->width ; /* fprintf(stderr, "lead = %d, space_size = %d, width = %d, to_width = %d\n", @@ -1316,44 +1307,33 @@ utf8_to_unicode ( const unsigned char *s ) } else if (c < 0xc2) { return 0; - } else if (c < 0xe0) - { - if (!((s[1] ^ 0x80) < 0x40)) + } else if (c < 0xe0) { + if (!((s[1] ^ 0x80) < 0x40)) return 0; return ((UNICODE_CHAR) (c & 0x1f) << 6) |(UNICODE_CHAR) (s[1] ^ 0x80); - } else if (c < 0xf0) - { - if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 - && (c >= 0xe1 || s[1] >= 0xa0))) - return 0; + } else if (c < 0xf0) { + if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (c >= 0xe1 || s[1] >= 0xa0))) + return 0; return ((UNICODE_CHAR) (c & 0x0f) << 12) | ((UNICODE_CHAR) (s[1] ^ 0x80) << 6) | (UNICODE_CHAR) (s[2] ^ 0x80); - } else if (c < 0xf8 && sizeof(UNICODE_CHAR)*8 >= 32) - { - if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 - && (s[3] ^ 0x80) < 0x40 - && (c >= 0xf1 || s[1] >= 0x90))) - return 0; - return ((UNICODE_CHAR) (c & 0x07) << 18) - | ((UNICODE_CHAR) (s[1] ^ 0x80) << 12) - | ((UNICODE_CHAR) (s[2] ^ 0x80) << 6) - | (UNICODE_CHAR) (s[3] ^ 0x80); - } else if (c < 0xfc && sizeof(UNICODE_CHAR)*8 >= 32) - { - if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 - && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 - && (c >= 0xf9 || s[1] >= 0x88))) - return 0; + } else if (c < 0xf8 && sizeof(UNICODE_CHAR) * 8 >= 32) { + if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (c >= 0xf1 || s[1] >= 0x90))) + return 0; + return ((UNICODE_CHAR)(c & 0x07) << 18) | ((UNICODE_CHAR)(s[1] ^ 0x80) << 12) | + ((UNICODE_CHAR)(s[2] ^ 0x80) << 6) | (UNICODE_CHAR)(s[3] ^ 0x80); + } else if (c < 0xfc && sizeof(UNICODE_CHAR) * 8 >= 32) { + if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && + (c >= 0xf9 || s[1] >= 0x88))) + return 0; return ((UNICODE_CHAR) (c & 0x03) << 24) | ((UNICODE_CHAR) (s[1] ^ 0x80) << 18) | ((UNICODE_CHAR) (s[2] ^ 0x80) << 12) | ((UNICODE_CHAR) (s[3] ^ 0x80) << 6) | (UNICODE_CHAR) (s[4] ^ 0x80); - } else if (c < 0xfe && sizeof(UNICODE_CHAR)*8 >= 32) - { - if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + } else if (c < 0xfe && sizeof(UNICODE_CHAR) * 8 >= 32) { + if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (s[5] ^ 0x80) < 0x40 && (c >= 0xfd || s[1] >= 0x84))) @@ -1364,7 +1344,7 @@ utf8_to_unicode ( const unsigned char *s ) | ((UNICODE_CHAR) (s[3] ^ 0x80) << 12) | ((UNICODE_CHAR) (s[4] ^ 0x80) << 6) | (UNICODE_CHAR) (s[5] ^ 0x80); - } + } return 0; } @@ -1732,8 +1712,8 @@ get_text_size_internal( const char *src_text, ASFont *font, ASTextAttributes *at Bool get_text_size( const char *src_text, ASFont *font, ASText3DType type, unsigned int *width, unsigned int *height ) { - ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0 }; - attr.type = type ; + ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0, 0, 0}; + attr.type = type ; if( IsUTF8Locale() ) attr.char_type = ASCT_UTF8 ; return get_text_size_internal( (char*)src_text, font, &attr, width, height, 0/*autodetect length*/, NULL ); @@ -1742,24 +1722,24 @@ get_text_size( const char *src_text, ASFont *font, ASText3DType type, unsigned i Bool get_unicode_text_size( const UNICODE_CHAR *src_text, ASFont *font, ASText3DType type, unsigned int *width, unsigned int *height ) { - ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Unicode, 8, 0, NULL, 0 }; - attr.type = type ; + ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Unicode, 8, 0, NULL, 0, 0, 0}; + attr.type = type ; return get_text_size_internal( (char*)src_text, font, &attr, width, height, 0/*autodetect length*/, NULL ); } Bool get_utf8_text_size( const char *src_text, ASFont *font, ASText3DType type, unsigned int *width, unsigned int *height ) { - ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_UTF8, 8, 0, NULL, 0 }; - attr.type = type ; + ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_UTF8, 8, 0, NULL, 0, 0, 0}; + attr.type = type ; return get_text_size_internal( (char*)src_text, font, &attr, width, height, 0/*autodetect length*/, NULL ); } Bool get_fancy_text_size( const void *src_text, ASFont *font, ASTextAttributes *attr, unsigned int *width, unsigned int *height, int length, int *x_positions ) { - ASTextAttributes internal_attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0 }; - if( attr != NULL ) + ASTextAttributes internal_attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0, 0, 0}; + if( attr != NULL ) { internal_attr = *attr; if( internal_attr.tab_size == 0 ) @@ -1879,19 +1859,18 @@ draw_text_internal( const char *text, ASFont *font, ASTextAttributes *attr, int get_text_size( text , font, attr->type, &width, &height ); if ( (width > attr->width) && (strchr(text, ' ')) ) { - char *tryPtr = strchr(text,' '); - char *oldTryPtr = tryPtr; - while (tryPtr) - { - *tryPtr = 0; - get_text_size( text , font, attr->type, &width, &height ); - if (width > attr->width) - *oldTryPtr = '\n'; - - *tryPtr = ' '; - oldTryPtr = tryPtr; - tryPtr = strchr(tryPtr + 1,' '); - } + char *tryPtr = strchr( (char *)text, ' '); // casting away this const could lead to UB, see https://stackoverflow.com/a/14368141/7471760 + char *oldTryPtr = tryPtr; + while (tryPtr) { + *tryPtr = 0; + get_text_size(text, font, attr->type, &width, &height); + if (width > attr->width) + *oldTryPtr = '\n'; + + *tryPtr = ' '; + oldTryPtr = tryPtr; + tryPtr = strchr(tryPtr + 1, ' '); + } } } @@ -2111,8 +2090,8 @@ LOCAL_DEBUG_OUT( "line_height is %d, space_size is %d, base_line is %d", line_he ASImage * draw_text( const char *text, ASFont *font, ASText3DType type, int compression ) { - ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0, ARGB32_White }; - attr.type = type ; + ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0, ARGB32_White, 0}; + attr.type = type ; if( IsUTF8Locale() ) attr.char_type = ASCT_UTF8 ; return draw_text_internal( text, font, &attr, compression, 0/*autodetect length*/ ); @@ -2121,23 +2100,23 @@ draw_text( const char *text, ASFont *font, ASText3DType type, int compression ) ASImage * draw_unicode_text( const UNICODE_CHAR *text, ASFont *font, ASText3DType type, int compression ) { - ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Unicode, 8, 0, NULL, 0, ARGB32_White }; - attr.type = type ; + ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Unicode, 8, 0, NULL, 0, ARGB32_White, 0}; + attr.type = type ; return draw_text_internal( (const char*)text, font, &attr, compression, 0/*autodetect length*/ ); } ASImage * draw_utf8_text( const char *text, ASFont *font, ASText3DType type, int compression ) { - ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_UTF8, 8, 0, NULL, 0, ARGB32_White }; - attr.type = type ; + ASTextAttributes attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_UTF8, 8, 0, NULL, 0, ARGB32_White, 0}; + attr.type = type ; return draw_text_internal( text, font, &attr, compression, 0/*autodetect length*/ ); } ASImage * draw_fancy_text( const void *text, ASFont *font, ASTextAttributes *attr, int compression, int length ) { - ASTextAttributes internal_attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0, ARGB32_White }; + ASTextAttributes internal_attr = {ASTA_VERSION_INTERNAL, 0, 0, ASCT_Char, 8, 0, NULL, 0, ARGB32_White, 0 }; if( attr != NULL ) { internal_attr = *attr; @@ -2237,12 +2216,24 @@ void print_asglyph( FILE* stream, ASFont* font, unsigned long c) #ifndef HAVE_XRENDER Bool afterimage_uses_xrender(){ return False;} - -void -draw_text_xrender( ASVisual *asv, const void *text, ASFont *font, ASTextAttributes *attr, int length, - int xrender_op, unsigned long xrender_src, unsigned long xrender_dst, - int xrender_xSrc, int xrender_ySrc, int xrender_xDst, int xrender_yDst ) -{} + +void draw_text_xrender(ASVisual *asv, const void *text, ASFont *font, ASTextAttributes *attr, int length, + int xrender_op, unsigned long xrender_src, unsigned long xrender_dst, int xrender_xSrc, + int xrender_ySrc, int xrender_xDst, int xrender_yDst) +{ + (void)asv; + (void)text; + (void)font; + (void)attr; + (void)length; + (void)xrender_op; + (void)xrender_src; + (void)xrender_dst; + (void)xrender_xSrc; + (void)xrender_ySrc; + (void)xrender_xDst; + (void)xrender_yDst; // silence unused variable warning +} #else Bool afterimage_uses_xrender(){ return True;} diff --git a/graf2d/asimage/src/libAfterImage/asim_afterbase.h b/graf2d/asimage/src/libAfterImage/asim_afterbase.h index 2b3cdbf1bfcec..06c81745a3bfc 100644 --- a/graf2d/asimage/src/libAfterImage/asim_afterbase.h +++ b/graf2d/asimage/src/libAfterImage/asim_afterbase.h @@ -17,7 +17,28 @@ # include # endif #endif - + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* # undef __CHAR_UNSIGNED__ */ +#endif + +#ifdef _WIN32 +typedef unsigned char boolean; +/* Define as `__inline' if that's what the C compiler calls it, or to nothing + if it is not supported. */ +#define inline +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const +#else +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ +#endif /* our own version of X Wrapper : */ #include "xwrap.h" @@ -158,7 +179,7 @@ void asim_nonGNUC_debugout_stub( const char *format, ...); #define LOCAL_DEBUG_CALLER_OUT(format,args...) \ do{ fprintf( stderr, "%s:%s:%s:> called from [%s] with args(" format ")\n", get_application_name(), __FILE__, __FUNCTION__, get_caller_func(), ## args );}while(0) #else -#define LOCAL_DEBUG_OUT(format,args...) +#define LOCAL_DEBUG_OUT(format, args...) #define LOCAL_DEBUG_CALLER_OUT(format,args...) #endif /* LOCAL_DEBUG */ @@ -212,8 +233,8 @@ void asim_nonGNUC_debugout_stub( const char *format, ...); #define START_TIME(started) time_t started = clock() #define SHOW_TIME(s,started) fprintf (stderr, "%s " s " time (clocks): %lu mlsec\n", __FUNCTION__, ((clock () - (started))*100)/CLOCKS_PER_SEC) #else -#define START_TIME(started) unsigned long started = 0 -#define SHOW_TIME(s,started) started = 0 +#define START_TIME(started) +#define SHOW_TIME(s, started) #endif /* from libAfterBase/safemalloc.h : */ diff --git a/graf2d/asimage/src/libAfterImage/asimage.c b/graf2d/asimage/src/libAfterImage/asimage.c index d4097c4d23bd7..aea8a719dbf86 100644 --- a/graf2d/asimage/src/libAfterImage/asimage.c +++ b/graf2d/asimage/src/libAfterImage/asimage.c @@ -24,13 +24,6 @@ #undef DEBUG_RECTS2 #endif -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - - #define USE_64BIT_FPU #include @@ -56,11 +49,7 @@ #include #endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else # include "afterbase.h" -#endif #include "asvisual.h" #include "scanline.h" #include "blender.h" @@ -91,22 +80,24 @@ ASVisual *get_default_asvisual() /* internal buffer used for compression/decompression */ -static CARD8 *__as_compression_buffer = NULL ; -static size_t __as_compression_buffer_len = 0; /* allocated size */ +// static CARD8 *__as_compression_buffer = NULL ; +// static size_t __as_compression_buffer_len = 0; /* allocated size */ +/* static inline CARD8* get_compression_buffer( size_t size ) { - if( size > __as_compression_buffer_len ) - __as_compression_buffer_len = (size+1023)&(~0x03FF) ; - return (__as_compression_buffer = realloc( __as_compression_buffer, __as_compression_buffer_len )); + if( size > __as_compression_buffer_len ) + __as_compression_buffer_len = (size+1023)&(~0x03FF) ; + return (__as_compression_buffer = realloc( __as_compression_buffer, __as_compression_buffer_len )); } - +*/ +/* static inline void release_compression_buffer( CARD8 *ptr ) { - /* do nothing so far */ + (void)ptr; // silence unused variable warning + // do nothing so far } - - +*/ #ifdef TRACK_ASIMAGES static ASHashTable *__as_image_registry = NULL ; @@ -165,6 +156,8 @@ flush_asimage_cache( ASImage *im ) XDestroyImage( im->alt.mask_ximage ); im->alt.mask_ximage = NULL ; } +#else + (void)im; // silence unused variable warning #endif } @@ -243,6 +236,9 @@ check_created_asimage( ASImage *im, unsigned int width, unsigned int height ) im = NULL ; #ifdef TRACK_ASIMAGES show_error( "failed to create ASImage of size %dx%d", width, height ); +#else + (void)width; + (void)height; // silence unused variable warning #endif }else { @@ -651,6 +647,8 @@ print_asimage_manager(ASImageManager *imageman) { #ifdef TRACK_ASIMAGES print_ashash( imageman->image_hash, string_print ); +#else + (void)imageman; // silence unused variable warning #endif } @@ -860,6 +858,7 @@ asimage_add_line_bgra (ASImage * im, register CARD32 * data, unsigned int y) unsigned int asimage_print_line (ASImage * im, ColorPart color, unsigned int y, unsigned long verbosity) { + (void)verbosity; // silence unused variable warning int colint = (int) color; if (AS_ASSERT(im) || colint < 0 || color >= IC_NUM_CHANNELS ) return 0; @@ -1169,7 +1168,7 @@ vectorize_asimage( ASImage *im, unsigned int max_colors, unsigned int dither, } /* ********************************************************************************/ -/* Convinience function - very fast image cloning : */ +/* Convenience function - very fast image cloning : */ /* ********************************************************************************/ ASImage* clone_asimage( ASImage *src, ASFlagType filter ) diff --git a/graf2d/asimage/src/libAfterImage/asimage.h b/graf2d/asimage/src/libAfterImage/asimage.h index 962c16603b881..35dcd5214c6e0 100644 --- a/graf2d/asimage/src/libAfterImage/asimage.h +++ b/graf2d/asimage/src/libAfterImage/asimage.h @@ -534,8 +534,6 @@ extern Bool asimage_use_mmx ; * im - pointer to valid ASImage structure. * NOTES * If there was XImage attached to it - it will be deallocated as well. - * EXAMPLE - * asview.c: ASView.5 *********/ /****f* libAfterImage/asimage/asimage_replace() * NAME @@ -1016,23 +1014,32 @@ do{ asimage_add_line((im), IC_RED, (src).red, (y)); \ if( get_flags((src).flags,SCL_DO_ALPHA))asimage_add_line((im), IC_ALPHA, (src).alpha, (y)); \ }while(0) -#define SCANLINE_FUNC(f,src,dst,scales,len) \ -do{ if( (src).offset_x > 0 || (dst).offset_x > 0 ) \ - LOCAL_DEBUG_OUT( "(src).offset_x = %d. (dst).offset_x = %d", (src).offset_x, (dst).offset_x ); \ - f((src).red+(src).offset_x, (dst).red+(dst).offset_x, (scales),(len)); \ - f((src).green+(src).offset_x,(dst).green+(dst).offset_x,(scales),(len)); \ - f((src).blue+(src).offset_x, (dst).blue+(dst).offset_x, (scales),(len)); \ - if(get_flags((src).flags,SCL_DO_ALPHA)) f((src).alpha+(src).offset_x,(dst).alpha+(dst).offset_x,(scales),(len)); \ - }while(0) - -#define SCANLINE_FUNC_FILTERED(f,src,dst,scales,len) \ -do{ if( (src).offset_x > 0 || (dst).offset_x > 0 ) \ - LOCAL_DEBUG_OUT( "(src).offset_x = %d. (dst).offset_x = %d", (src).offset_x, (dst).offset_x ); \ - if(get_flags((src).flags,SCL_DO_RED)) f((src).red+(src).offset_x, (dst).red+(dst).offset_x, (scales),(len)); \ - if(get_flags((src).flags,SCL_DO_GREEN)) f((src).green+(src).offset_x,(dst).green+(dst).offset_x,(scales),(len)); \ - if(get_flags((src).flags,SCL_DO_BLUE)) f((src).blue+(src).offset_x, (dst).blue+(dst).offset_x, (scales),(len)); \ - if(get_flags((src).flags,SCL_DO_ALPHA)) f((src).alpha+(src).offset_x,(dst).alpha+(dst).offset_x,(scales),(len)); \ - }while(0) +#define SCANLINE_FUNC(f, src, dst, scales, len) \ + do { \ + if ((src).offset_x > 0 || (dst).offset_x > 0) { \ + LOCAL_DEBUG_OUT("(src).offset_x = %d. (dst).offset_x = %d", (src).offset_x, (dst).offset_x); \ + } \ + f((src).red + (src).offset_x, (dst).red + (dst).offset_x, (scales), (len)); \ + f((src).green + (src).offset_x, (dst).green + (dst).offset_x, (scales), (len)); \ + f((src).blue + (src).offset_x, (dst).blue + (dst).offset_x, (scales), (len)); \ + if (get_flags((src).flags, SCL_DO_ALPHA)) \ + f((src).alpha + (src).offset_x, (dst).alpha + (dst).offset_x, (scales), (len)); \ + } while (0) + +#define SCANLINE_FUNC_FILTERED(f, src, dst, scales, len) \ + do { \ + if ((src).offset_x > 0 || (dst).offset_x > 0) { \ + LOCAL_DEBUG_OUT("(src).offset_x = %d. (dst).offset_x = %d", (src).offset_x, (dst).offset_x); \ + } \ + if (get_flags((src).flags, SCL_DO_RED)) \ + f((src).red + (src).offset_x, (dst).red + (dst).offset_x, (scales), (len)); \ + if (get_flags((src).flags, SCL_DO_GREEN)) \ + f((src).green + (src).offset_x, (dst).green + (dst).offset_x, (scales), (len)); \ + if (get_flags((src).flags, SCL_DO_BLUE)) \ + f((src).blue + (src).offset_x, (dst).blue + (dst).offset_x, (scales), (len)); \ + if (get_flags((src).flags, SCL_DO_ALPHA)) \ + f((src).alpha + (src).offset_x, (dst).alpha + (dst).offset_x, (scales), (len)); \ + } while (0) #define CHOOSE_SCANLINE_FUNC(r,src,dst,scales,len) \ switch(r) \ diff --git a/graf2d/asimage/src/libAfterImage/asstorage.c b/graf2d/asimage/src/libAfterImage/asstorage.c index 6fd14bc581d3a..fd9d09496fce0 100644 --- a/graf2d/asimage/src/libAfterImage/asstorage.c +++ b/graf2d/asimage/src/libAfterImage/asstorage.c @@ -27,12 +27,6 @@ #endif #define DO_CLOCKING -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #if TIME_WITH_SYS_TIME # include # include @@ -51,18 +45,9 @@ #endif #include -#ifndef HAVE_ZLIB_H -#include "zlib/zlib.h" -#else #include -#endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else # include "afterbase.h" -#endif - #include "asstorage.h" /* default storage : */ @@ -716,9 +701,9 @@ compress_stored_data( ASStorage *storage, CARD8 *data, int size, ASFlagType *fla /* TODO: just a stub for now - need to implement compression */ int comp_size = size ; CARD8 *buffer = data ; - size_t buf_size = size ; + // size_t buf_size = size ; - static compute_diff_func_type compute_diff_func[2][4] = + static compute_diff_func_type compute_diff_func[2][4] = { { compute_diff32, compute_diff32_8bitshift, @@ -784,8 +769,8 @@ compress_stored_data( ASStorage *storage, CARD8 *data, int size, ASFlagType *fla #endif } buffer = storage->comp_buf ; - buf_size = storage->comp_buf_size ; - if( buffer ) + // buf_size = storage->comp_buf_size ; + if( buffer ) { if( get_flags( *flags, ASStorage_Bitmap ) ) { @@ -889,7 +874,8 @@ decompress_stored_data( ASStorage *storage, CARD8 *data, int size, int uncompres { CARD8 *buffer = data ; - LOCAL_DEBUG_OUT( "size = %d, uncompressed_size = %d, flags = 0x%lX", size, uncompressed_size, flags ); + (void)uncompressed_size; // silence unused variable warning when LOCAL_DEBUG_OUT is void + LOCAL_DEBUG_OUT( "size = %d, uncompressed_size = %d, flags = 0x%lX", size, uncompressed_size, flags ); if( get_flags( flags, ASStorage_RLEDiffCompress )) { buffer = storage->comp_buf ; @@ -1014,7 +1000,8 @@ destroy_asstorage_block( ASStorageBlock *block ) static int select_storage_block( ASStorage *storage, int compressed_size, ASFlagType flags, int block_id_start ) { - int i ; + (void)flags; // unused variable + int i ; int new_block = -1 ; compressed_size += ASStorageSlot_SIZE; i = block_id_start - 1 ; @@ -1498,13 +1485,12 @@ convert_slot_to_ref( ASStorage *storage, ASStorageID id ) * there is enough space in its block, otherwise we have to relocate it * into different block, which is slower. */ - if( block->total_free > sizeof(ASStorageID)) - { - slot_id = store_data_in_block( block, (CARD8*)&target_id, + if (block->total_free > (int)sizeof(ASStorageID)) { + slot_id = store_data_in_block( block, (CARD8*)&target_id, sizeof(ASStorageID), sizeof(ASStorageID), 0, ASStorage_Reference ); - } - LOCAL_DEBUG_OUT( "block = %p, block->total_free = %d, slot_id = 0x%X", block, block->total_free, slot_id ); + } + LOCAL_DEBUG_OUT( "block = %p, block->total_free = %d, slot_id = 0x%X", block, block->total_free, slot_id ); if( slot_id > 0 ) { /* We can use fast strategy : now we need to swap contents of the slots */ diff --git a/graf2d/asimage/src/libAfterImage/asvisual.c b/graf2d/asimage/src/libAfterImage/asvisual.c index 4cdeb7c3117b8..cd0d7251bc97f 100644 --- a/graf2d/asimage/src/libAfterImage/asvisual.c +++ b/graf2d/asimage/src/libAfterImage/asvisual.c @@ -16,12 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #define LOCAL_DEBUG #undef DEBUG_SL2XIMAGE #include @@ -34,12 +28,8 @@ #ifdef HAVE_STDARG_H #include #endif - -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif + +#include "afterbase.h" #include "asvisual.h" #include "scanline.h" @@ -69,7 +59,9 @@ void _XInitImageFuncPtrs(XImage*); int asvisual_empty_XErrorHandler (Display * dpy, XErrorEvent * event) { - return 0; + (void)dpy; // silence unused variable warning + (void)event; // silence unused variable warning + return 0; } /***************************************************************************/ #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT) @@ -113,6 +105,7 @@ ARGB32_manhattan_distance (long a, long b) ***************************************************************************/ int get_bits_per_pixel(Display *dpy, int depth) { + (void)dpy; // silence unused variable warning #if 0 #ifndef X_DISPLAY_MISSING register ScreenFormat *fmt = dpy->pixmap_format; @@ -136,8 +129,8 @@ int get_bits_per_pixel(Display *dpy, int depth) ASVisual *_set_default_asvisual( ASVisual *new_v ); #ifndef X_DISPLAY_MISSING -static XColor black_xcol = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue }; -static XColor white_xcol = { 0, 0xFFFF, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue }; +static XColor black_xcol = {0, 0x0000, 0x0000, 0x0000, DoRed | DoGreen | DoBlue, 0}; +static XColor white_xcol = {0, 0xFFFF, 0xFFFF, 0xFFFF, DoRed | DoGreen | DoBlue, 0}; static void find_useable_visual( ASVisual *asv, Display *dpy, int screen, Window root, XVisualInfo *list, int nitems, @@ -246,6 +239,12 @@ query_screen_visual_id( ASVisual *asv, Display *dpy, int screen, Window root, in { NULL , 0 , 0 , 15 , DirectColor, 0x0 , 0xE003 , 0x0 , 0 , 0 }, { NULL , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, } ; +#else + (void)screen; + (void)root; + (void)default_depth; + (void)visual_id; + (void)cmap; // silence unused variable warning #endif /*ifndef X_DISPLAY_MISSING */ if( asv == NULL ) return False ; @@ -360,6 +359,13 @@ create_asvisual_for_id( Display *dpy, int screen, int default_depth, VisualID vi asv = NULL ; } } +#else + (void)dpy; + (void)screen; + (void)default_depth; + (void)visual_id; + (void)cmap; + (void)reusable_memory; // silence unused variable warning #endif /*ifndef X_DISPLAY_MISSING */ _set_default_asvisual( asv ); return asv; @@ -464,11 +470,13 @@ visual2visual_prop( ASVisual *asv, size_t *size_ret, } if( size_ret ) *size_ret = size; +#else + (void)size_ret; // silence unused variable warning #endif /*ifndef X_DISPLAY_MISSING */ - if( version_ret ) - *version_ret = (1<<16)+0; /* version is 1.0 */ - *data_ret = prop ; - return True; + if (version_ret) + *version_ret = (1 << 16) + 0; /* version is 1.0 */ + *data_ret = prop; + return True; } Bool @@ -528,7 +536,7 @@ visual_prop2visual( ASVisual *asv, Display *dpy, int screen, }else asv->as_colormap_type = ACM_None ; /* just in case */ #else - + (void)screen; // silence unused variable warning #endif /*ifndef X_DISPLAY_MISSING */ return True; } @@ -636,7 +644,8 @@ make_reverse_colormap( unsigned long *cmap, size_t size, int depth, unsigned sho ASHashTable * make_reverse_colorhash( unsigned long *cmap, size_t size, int depth, unsigned short mask, unsigned short shift ) { - ASHashTable *hash = create_ashash( 0, NULL, NULL, NULL ); + (void)depth; // silence unused variable warning + ASHashTable *hash = create_ashash( 0, NULL, NULL, NULL ); register unsigned int i ; if( hash ) @@ -705,6 +714,8 @@ setup_pseudo_visual( ASVisual *asv ) asv->true_depth, 0x000F, 4 ); } } +#else + (void)asv; // silence unused variable warning #endif /*ifndef X_DISPLAY_MISSING */ } @@ -896,6 +907,8 @@ setup_as_colormap( ASVisual *asv ) asv->as_colormap = cmap ; asv->as_colormap_reverse.hash = make_reverse_colorhash( cmap, 4096, asv->true_depth, 0x000F, 4 ); } +#else + (void)asv; // silence unused variable warning #endif /*ifndef X_DISPLAY_MISSING */ } @@ -970,7 +983,17 @@ LOCAL_DEBUG_OUT( "Colormap %lX, parent %lX, %ux%u%+d%+d, bw = %d, class %d", wclass, asv->visual_info.visual, mask, attributes); #else - return None ; + (void)asv; + (void)parent; + (void)x; + (void)y; + (void)width; + (void)height; + (void)border_width; + (void)wclass; + (void)mask; + (void)attributes; // silence unused variable warning + return None; #endif /*ifndef X_DISPLAY_MISSING */ } @@ -990,6 +1013,11 @@ create_visual_gc( ASVisual *asv, Window root, unsigned long mask, XGCValues *gcv if( asv->scratch_window != None ) gc = XCreateGC( asv->dpy, asv->scratch_window, gcvalues?mask:0, gcvalues?gcvalues:&scratch_gcv ); } +#else + (void)asv; + (void)root; + (void)mask; + (void)gcvalues; // silence unused variable warning #endif return gc; } @@ -1009,7 +1037,12 @@ create_visual_pixmap( ASVisual *asv, Window root, unsigned int width, unsigned i } return p; #else - return None ; + (void)asv; + (void)root; + (void)width; + (void)height; + (void)depth; // silence unused variable warning + return None ; #endif /*ifndef X_DISPLAY_MISSING */ } @@ -1030,7 +1063,9 @@ destroy_visual_pixmap( ASVisual *asv, Pixmap *ppmap ) static int quiet_xerror_handler (Display * dpy, XErrorEvent * error) { - return 0; + (void)dpy; // silence unused variable warning + (void)error; // silence unused variable warning + return 0; } #endif @@ -1049,6 +1084,9 @@ get_dpy_drawable_size (Display *drawable_dpy, Drawable d, unsigned int *ret_w, u result = XGetGeometry (drawable_dpy, d, &root, &junk, &junk, ret_w, ret_h, &ujunk, &ujunk); XSetErrorHandler (oldXErrorHandler); } +#else + (void)drawable_dpy; + (void)d; // silence unused variable warning #endif if ( result == 0) { @@ -1092,6 +1130,10 @@ get_dpy_window_position (Display *window_dpy, Window root, Window w, int *px, in while( transp_y > rootHeight ) transp_y -= rootHeight ; } } +#else + (void)window_dpy; + (void)root; + (void)w; // silence unused variable warning #endif if( px ) *px = x; @@ -1486,7 +1528,11 @@ XImage *ASGetXImage( ASVisual *asv, Drawable d, Bool enable_shmem_images (){return False; } void disable_shmem_images(){} -void *check_XImage_shared( XImage *xim ) {return NULL ; } +void *check_XImage_shared(XImage *xim) +{ + (void)xim; // silence unused variable warning + return NULL; +} Bool ASPutXImage( ASVisual *asv, Drawable d, GC gc, XImage *xim, int src_x, int src_y, int dest_x, int dest_y, @@ -1497,7 +1543,17 @@ Bool ASPutXImage( ASVisual *asv, Drawable d, GC gc, XImage *xim, return False ; return XPutImage( asv->dpy, d, gc, xim, src_x, src_y, dest_x, dest_y,width, height ); #else - return False; + (void)asv; + (void)d; + (void)gc; + (void)xim; + (void)src_x; + (void)src_y; + (void)dest_x; + (void)dest_y; + (void)width; + (void)height; // silence unused variable warning + return False; #endif } @@ -1510,7 +1566,14 @@ XImage * ASGetXImage( ASVisual *asv, Drawable d, return NULL ; return XGetImage( asv->dpy, d, x, y, width, height, plane_mask, ZPixmap ); #else - return NULL ; + (void)asv; + (void)d; + (void)x; + (void)y; + (void)width; + (void)height; + (void)plane_mask; // silence unused variable warning + return NULL ; #endif } @@ -1591,10 +1654,10 @@ create_visual_ximage( ASVisual *asv, unsigned int width, unsigned int height, un #endif if( ximage == NULL ) { - ximage = XCreateImage (asv->dpy, asv->visual_info.visual, (depth==0)?asv->visual_info.depth/*true_depth*/:depth, ZPixmap, - 0, NULL, MAX(width,(unsigned int)1), MAX(height,(unsigned int)1), - unit, 0); - if (ximage != NULL) + ximage = XCreateImage(asv->dpy, asv->visual_info.visual, + (depth == 0) ? (unsigned int)asv->visual_info.depth /*true_depth*/ : depth, ZPixmap, 0, + NULL, MAX(width, (unsigned int)1), MAX(height, (unsigned int)1), unit, 0); + if (ximage != NULL) { _XInitImageFuncPtrs (ximage); ximage->obdata = NULL; @@ -1610,7 +1673,11 @@ create_visual_ximage( ASVisual *asv, unsigned int width, unsigned int height, un } return ximage; #else - return NULL ; + (void)asv; + (void)width; + (void)height; + (void)depth; // silence unused variable warning + return NULL ; #endif /*ifndef X_DISPLAY_MISSING */ } /* this is the vehicle to use static allocated buffer for temporary XImages @@ -1645,11 +1712,10 @@ create_visual_scratch_ximage( ASVisual *asv, unsigned int width, unsigned int he if( ximage == NULL ) { - ximage = XCreateImage (asv->dpy, asv->visual_info.visual, - (depth==0)?asv->visual_info.depth/*true_depth*/:depth, ZPixmap, - 0, NULL, MAX(width,(unsigned int)1), MAX(height,(unsigned int)1), - unit, 0); - if (ximage != NULL) + ximage = XCreateImage(asv->dpy, asv->visual_info.visual, + (depth == 0) ? (unsigned int)asv->visual_info.depth /*true_depth*/ : depth, ZPixmap, 0, + NULL, MAX(width, (unsigned int)1), MAX(height, (unsigned int)1), unit, 0); + if (ximage != NULL) { data = get_scratch_data(ximage->bytes_per_line * ximage->height); if( data == NULL ) @@ -1665,6 +1731,10 @@ create_visual_scratch_ximage( ASVisual *asv, unsigned int width, unsigned int he } return ximage; #else + (void)asv; + (void)width; + (void)height; + (void)depth; // silence unused variable warning return NULL ; #endif /*ifndef X_DISPLAY_MISSING */ } @@ -1732,45 +1802,53 @@ query_pixel_color( ASVisual *asv, unsigned long pixel, CARD32 *r, CARD32 *g, CAR CARD32 color2pixel32bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - *pixel = ARGB32_RED8(encoded_color)|(ARGB32_GREEN8(encoded_color)<<8)|(ARGB32_BLUE8(encoded_color)<<16); + (void)asv; // silence unused variable warning + *pixel = ARGB32_RED8(encoded_color)|(ARGB32_GREEN8(encoded_color)<<8)|(ARGB32_BLUE8(encoded_color)<<16); return 0; } CARD32 color2pixel32rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - *pixel = encoded_color&0x00FFFFFF; + (void)asv; // silence unused variable warning + *pixel = encoded_color&0x00FFFFFF; return 0; } CARD32 color2pixel24bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - *pixel = encoded_color&0x00FFFFFF; + (void)asv; // silence unused variable warning + *pixel = encoded_color&0x00FFFFFF; return 0; } CARD32 color2pixel24rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - *pixel = encoded_color&0x00FFFFFF; + (void)asv; // silence unused variable warning + *pixel = encoded_color&0x00FFFFFF; return 0; } CARD32 color2pixel16bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - register CARD32 c = encoded_color ; - *pixel = ((c&0x000000F8)<<8)|((c&0x0000FC00)>>5)|((c&0x00F80000)>>19); + (void)asv; // silence unused variable warning + register CARD32 c = encoded_color; + *pixel = ((c & 0x000000F8) << 8) | ((c & 0x0000FC00) >> 5) | ((c & 0x00F80000) >> 19); return (c>>1)&0x00030103; } CARD32 color2pixel16rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - register CARD32 c = encoded_color ; + (void)asv; // silence unused variable warning + register CARD32 c = encoded_color ; *pixel = ((c&0x00F80000)>>8)|((c&0x0000FC00)>>5)|((c&0x000000F8)>>3); return (c>>1)&0x00030103; } CARD32 color2pixel15bgr(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - register CARD32 c = encoded_color ; + (void)asv; // silence unused variable warning + register CARD32 c = encoded_color ; *pixel = ((c&0x000000F8)<<7)|((c&0x0000F800)>>6)|((c&0x00F80000)>>19); return (c>>1)&0x00030303; } CARD32 color2pixel15rgb(ASVisual *asv, CARD32 encoded_color, unsigned long *pixel) { - register CARD32 c = encoded_color ; + (void)asv; // silence unused variable warning + register CARD32 c = encoded_color ; *pixel = ((c&0x00F80000)>>9)|((c&0x0000F800)>>6)|((c&0x000000F8)>>3); return (c>>1)&0x00030303; } @@ -1797,21 +1875,69 @@ CARD32 color2pixel_pseudo12bpp( ASVisual *asv, CARD32 encoded_color, unsigned lo } void pixel2color32rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color32bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color24rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color24bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color16rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color16bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color15rgb(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void pixel2color15bgr(ASVisual *asv, unsigned long pixel, CARD32 *red, CARD32 *green, CARD32 *blue) -{} +{ + (void)asv; + (void)pixel; + (void)red; + (void)green; + (void)blue; // silence unused variable warning +} void ximage2scanline32(ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { @@ -1819,8 +1945,9 @@ void ximage2scanline32(ASVisual *asv, XImage *xim, ASScanline *sl, int y, regis register CARD32 *a = sl->alpha+sl->offset_x; int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x); register CARD32 *src = (CARD32*)xim_data ; -/* src += sl->offset_x; */ -/*fprintf( stderr, "%d: ", y);*/ + (void)y; // silence unused variable warning + /* src += sl->offset_x; */ + /*fprintf( stderr, "%d: ", y);*/ #ifdef WORDS_BIGENDIAN if( !asv->msb_first ) @@ -1851,7 +1978,8 @@ void ximage2scanline32(ASVisual *asv, XImage *xim, ASScanline *sl, int y, regis void ximage2scanline16( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { - register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; + (void)y; // silence unused variable warning + register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; register CARD16 *src = (CARD16*)xim_data ; register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; #ifdef WORDS_BIGENDIAN @@ -1878,7 +2006,8 @@ void ximage2scanline16( ASVisual *asv, XImage *xim, ASScanline *sl, int y, regi } void ximage2scanline15( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { - register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; + (void)y; // silence unused variable warning + register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; register CARD16 *src = (CARD16*)xim_data ; register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; #ifdef WORDS_BIGENDIAN @@ -1908,7 +2037,8 @@ void ximage2scanline15( ASVisual *asv, XImage *xim, ASScanline *sl, int y, regi void ximage2scanline_pseudo3bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { - register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; + (void)xim_data; // silence unused variable warning + register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; do @@ -2014,6 +2144,7 @@ void scanline2ximage32( ASVisual *asv, XImage *xim, ASScanline *sl, int y, regi register CARD32 *a = sl->alpha+sl->offset_x; register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x); register CARD32 *src = (CARD32*)xim_data; + (void)y; // silence unused variable warning /* src += sl->offset_x ; */ /*fprintf( stderr, "%d: ", y);*/ #ifdef WORDS_BIGENDIAN @@ -2041,7 +2172,8 @@ void scanline2ximage32( ASVisual *asv, XImage *xim, ASScanline *sl, int y, regi void scanline2ximage16( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { - register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; + (void)y; // silence unused variable warning + register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; register CARD16 *src = (CARD16*)xim_data ; register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]); @@ -2099,7 +2231,8 @@ void scanline2ximage16( ASVisual *asv, XImage *xim, ASScanline *sl, int y, regi void scanline2ximage15( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { - register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; + (void)y; // silence unused variable warning + register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; register CARD16 *src = (CARD16*)xim_data ; register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]); @@ -2161,7 +2294,8 @@ void scanline2ximage15( ASVisual *asv, XImage *xim, ASScanline *sl, int y, regi void scanline2ximage_pseudo3bpp( ASVisual *asv, XImage *xim, ASScanline *sl, int y, register unsigned char *xim_data ) { - register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; + (void)xim_data; // silence unused variable warning + register CARD32 *r = sl->xc1+sl->offset_x, *g = sl->xc2+sl->offset_x, *b = sl->xc3+sl->offset_x; register int i = MIN((unsigned int)(xim->width),sl->width-sl->offset_x)-1; register CARD32 c = (r[i]<<20) | (g[i]<<10) | (b[i]); diff --git a/graf2d/asimage/src/libAfterImage/asvisual.h b/graf2d/asimage/src/libAfterImage/asvisual.h index 0f80ab5ea4ae1..e2c41fee8b7b1 100644 --- a/graf2d/asimage/src/libAfterImage/asvisual.h +++ b/graf2d/asimage/src/libAfterImage/asvisual.h @@ -1,6 +1,12 @@ #ifndef _ASVISUAL_H_HEADER_INCLUDED #define _ASVISUAL_H_HEADER_INCLUDED +#if !defined(X_DISPLAY_MISSING) +#include +#include +#endif +#include "asim_afterbase.h" + #ifdef __cplusplus extern "C" { #endif @@ -200,8 +206,6 @@ long ARGB32_manhattan_distance (long a, long b); * create_visual_ximage() - to create XImage * ASVisual could be dealolocated and its resources freed with : * destroy_asvisual() - * EXAMPLE - * asview.c: ASView * SOURCE */ typedef struct ASVisual @@ -480,8 +484,6 @@ void setup_as_colormap( ASVisual *asv ); * Cleanup function. Frees all the memory and deallocates all the * resources. If reusable is False it will also free the object, pointed * to by asv. - * EXAMPLE - * asview.c: ASView.2 *********/ ASVisual *create_asvisual_for_id( Display *dpy, int screen, int default_depth, VisualID visual_id, Colormap cmap, diff --git a/graf2d/asimage/src/libAfterImage/blender.c b/graf2d/asimage/src/libAfterImage/blender.c index e18ec60949b03..b368022376716 100644 --- a/graf2d/asimage/src/libAfterImage/blender.c +++ b/graf2d/asimage/src/libAfterImage/blender.c @@ -16,12 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - /*#define LOCAL_DEBUG*/ /*#define DO_CLOCKING*/ @@ -30,11 +24,7 @@ #endif #include -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #include "asvisual.h" #include "scanline.h" #include "blender.h" @@ -308,25 +298,23 @@ typedef struct merge_scanlines_func_desc { char *short_desc; }merge_scanlines_func_desc; -merge_scanlines_func_desc std_merge_scanlines_func_list[] = -{ - { "add", 3, add_scanlines, "color addition with saturation" }, - { "alphablend", 10, alphablend_scanlines, "alpha-blending" }, - { "allanon", 7, allanon_scanlines, "color values averaging" }, - { "colorize", 8, colorize_scanlines, "hue and saturate bottom image same as top image" }, - { "darken", 6, darken_scanlines, "use lowest color value from both images" }, - { "diff", 4, diff_scanlines, "use absolute value of the color difference between two images" }, - { "dissipate", 9, dissipate_scanlines, "randomly alpha-blend images"}, - { "hue", 3, hue_scanlines, "hue bottom image same as top image" }, - { "lighten", 7, lighten_scanlines, "use highest color value from both images" }, - { "overlay", 7, overlay_scanlines, "some weird image overlaying(see GIMP)" }, - { "saturate", 8, saturate_scanlines, "saturate bottom image same as top image"}, - { "screen", 6, screen_scanlines, "another weird image overlaying(see GIMP)" }, - { "sub", 3, sub_scanlines, "color substraction with saturation" }, - { "tint", 4, tint_scanlines, "tinting image with image" }, - { "value", 5, value_scanlines, "value bottom image same as top image" }, - { NULL, 0, NULL } -}; +merge_scanlines_func_desc std_merge_scanlines_func_list[] = { + {"add", 3, add_scanlines, "color addition with saturation"}, + {"alphablend", 10, alphablend_scanlines, "alpha-blending"}, + {"allanon", 7, allanon_scanlines, "color values averaging"}, + {"colorize", 8, colorize_scanlines, "hue and saturate bottom image same as top image"}, + {"darken", 6, darken_scanlines, "use lowest color value from both images"}, + {"diff", 4, diff_scanlines, "use absolute value of the color difference between two images"}, + {"dissipate", 9, dissipate_scanlines, "randomly alpha-blend images"}, + {"hue", 3, hue_scanlines, "hue bottom image same as top image"}, + {"lighten", 7, lighten_scanlines, "use highest color value from both images"}, + {"overlay", 7, overlay_scanlines, "some weird image overlaying(see GIMP)"}, + {"saturate", 8, saturate_scanlines, "saturate bottom image same as top image"}, + {"screen", 6, screen_scanlines, "another weird image overlaying(see GIMP)"}, + {"sub", 3, sub_scanlines, "color substraction with saturation"}, + {"tint", 4, tint_scanlines, "tinting image with image"}, + {"value", 5, value_scanlines, "value bottom image same as top image"}, + {NULL, 0, NULL, NULL}}; merge_scanlines_func blend_scanlines_name2func( const char *name ) @@ -460,6 +448,7 @@ tint_scanlines( ASScanline *bottom, ASScanline *top, int offset ) bb[i] = (bb[i]*(tb[i]>>1))>>15 ; } } + (void)ba; // silence unused variable warning } void /* addition with saturation : */ diff --git a/graf2d/asimage/src/libAfterImage/bmp.c b/graf2d/asimage/src/libAfterImage/bmp.c index ea7e0a1e90f65..9484966a8ded0 100644 --- a/graf2d/asimage/src/libAfterImage/bmp.c +++ b/graf2d/asimage/src/libAfterImage/bmp.c @@ -1,6 +1,6 @@ /* This file contains code for unified image loading from many file formats */ /********************************************************************/ -/* Copyright (c) 2001 Sasha Vasko */ +/* Copyright (c) 2001 Sasha Vasko */ /********************************************************************/ /* * This library is free software; you can redistribute it and/or @@ -23,15 +23,12 @@ #undef DEBUG_TRANSP_GIF #ifdef _WIN32 -# include "win32/config.h" # include -# include "win32/afterbase.h" #else -# include "config.h" # include -# include "afterbase.h" #endif +#include "afterbase.h" #include "asimage.h" #include "imencdec.h" #include "import.h" @@ -52,14 +49,13 @@ dib_data_to_scanline( ASScanline *buf, switch( bmp_info->biBitCount ) { case 1 : - for( x = 0 ; x < bmp_info->biWidth ; x++ ) - { - int entry = (data[x>>3]&(1<<(x&0x07)))?cmap_entry_size:0 ; + for (x = 0; x < (int)bmp_info->biWidth; x++) { + int entry = (data[x>>3]&(1<<(x&0x07)))?cmap_entry_size:0 ; buf->red[x] = cmap[entry+2]; buf->green[x] = cmap[entry+1]; buf->blue[x] = cmap[entry]; - } - break ; + } + break ; case 4 : for( x = 0 ; x < (int)bmp_info->biWidth ; x++ ) { @@ -85,11 +81,14 @@ dib_data_to_scanline( ASScanline *buf, case 16 : for( x = 0 ; x < (int)bmp_info->biWidth ; ++x ) { - CARD8 c1 = data[x] ; - CARD8 c2 = data[++x]; - buf->blue[x] = c1&0x1F; - buf->green[x] = ((c1>>5)&0x07)|((c2<<3)&0x18); - buf->red[x] = ((c2>>2)&0x1F); + CARD8 c1 = data[2 * x]; + CARD8 c2 = data[2 * x + 1]; + // Assumed RGB555, ie R.G.B.A.X 5.5.5.0.1 + const CARD32 bufmax = 0xFF; + const CARD32 chmax = 0x1F; + buf->blue[x] = ((c1 & 0x1F) * bufmax) / chmax; + buf->green[x] = ((((c1 >> 5) & 0x07) | ((c2 << 3) & 0x18)) * bufmax) / chmax; + buf->red[x] = ((((c2 >> 2) & 0x1F)) * bufmax) / chmax; } break ; default: @@ -360,7 +359,8 @@ bmp_write16 (FILE *fp, CARD16 *data, int count) Bool ASImage2bmp ( ASImage *im, const char *path, ASImageExportParams *params ) { - Bool success = False; + (void)params; // silence unused variable warning + Bool success = False; FILE *outfile = NULL ; START_TIME(started); @@ -390,8 +390,8 @@ ASImage2bmp ( ASImage *im, const char *path, ASImageExportParams *params ) bmp_write32( outfile, &bmi->bmiHeader.biCompression, 6 ); /* writing off the bitmapbits */ - if (fwrite( bmbits, sizeof(CARD8), bits_size, outfile ) == bits_size) - success = True; + if ((int)fwrite(bmbits, sizeof(CARD8), bits_size, outfile) == bits_size) + success = True; free( bmbits ); free( bmi ); @@ -416,9 +416,9 @@ bmp_read32 (FILE *fp, CARD32 *data, int count) CARD8 *raw = (CARD8*)data ; #endif total = fread((char*) data, sizeof (CARD8), count<<2, fp)>>2; - count = 0 ; #ifdef WORDS_BIGENDIAN /* BMPs are encoded as Little Endian */ - while( count < total ) + count = 0; + while( count < total ) { data[count] = (raw[0]<<24)|(raw[1]<<16)|(raw[2]<<8)|raw[3]; ++count ; @@ -439,9 +439,9 @@ bmp_read16 (FILE *fp, CARD16 *data, int count) CARD8 *raw = (CARD8*)data ; #endif total = fread((char*) data, sizeof (CARD8), count<<1, fp)>>1; - count = 0 ; #ifdef WORDS_BIGENDIAN /* BMPs are encoded as Little Endian */ - while( count < total ) + count = 0; + while( count < total ) { data[count] = (raw[0]<<16)|raw[1]; ++count ; @@ -515,11 +515,12 @@ read_bmp_image( FILE *infile, size_t data_offset, BITMAPINFOHEADER *bmp_info, size_t ret; cmap = safemalloc( cmap_entries * cmap_entry_size ); ret = fread(cmap, sizeof (CARD8), cmap_entries * cmap_entry_size, infile); - if (ret != cmap_entries * cmap_entry_size) { - if (cmap) free(cmap); - return NULL; - } - } + if ((int)ret != cmap_entries * cmap_entry_size) { + if (cmap) + free(cmap); + return NULL; + } + } if( add_colormap ) data_offset += cmap_entries*cmap_entry_size ; diff --git a/graf2d/asimage/src/libAfterImage/char2uni.c b/graf2d/asimage/src/libAfterImage/char2uni.c index 63ced1d479540..753f9e4f5a36f 100644 --- a/graf2d/asimage/src/libAfterImage/char2uni.c +++ b/graf2d/asimage/src/libAfterImage/char2uni.c @@ -27,21 +27,11 @@ * Suite 330, Boston, MA 02111-1307, USA. */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #define LOCAL_DEBUG /*#define DO_CLOCKING*/ #include -#ifdef _WIN32 -# include "win32/afterbase.h" -#else # include "afterbase.h" -#endif #include "char2uni.h" @@ -773,10 +763,9 @@ parse_short_charset_name( const char *name ) ASSupportedCharsets parse_charset_name( const char *name ) { - ASSupportedCharsets set = 0; - int i = 0; - if( name == NULL || name[0] == '\0' || name[1] == '\0' ) /* that includes locale "C" */ - return CHARSET_ISO8859_1 ; + int i = 0; + if (name == NULL || name[0] == '\0' || name[1] == '\0') /* that includes locale "C" */ + return CHARSET_ISO8859_1 ; /* if locale name came from LANG env var it may have formatof : * language.charset@modifier * we only need charset part of it here: */ @@ -939,8 +928,8 @@ parse_charset_name( const char *name ) if( name[3] == 'A' || name[3] == 'a' ) return CHARSET_CP1252 ; } - set = CHARSET_CP1250 ; - }else if( name[0] == 'A' || name[0] == 'a' ) /* ARABIC or ASMO-708 */ + return CHARSET_CP1250; + }else if( name[0] == 'A' || name[0] == 'a' ) /* ARABIC or ASMO-708 */ { return CHARSET_ISO8859_6 ; }else if( name[0] == 'G' || name[0] == 'g' ) /* GREEK or GREEK8 */ @@ -957,6 +946,7 @@ parse_charset_name( const char *name ) } #if 0 + ASSupportedCharsets set = 0; while( set < SUPPORTED_CHARSETS_NUM ) { char **aliases =&(_as_charset_names[set][0]) ; diff --git a/graf2d/asimage/src/libAfterImage/config.guess b/graf2d/asimage/src/libAfterImage/config.guess deleted file mode 100755 index 48a684601bd23..0000000000000 --- a/graf2d/asimage/src/libAfterImage/config.guess +++ /dev/null @@ -1,1815 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2024 Free Software Foundation, Inc. - -# shellcheck disable=SC2006,SC2268 # see below for rationale - -timestamp='2024-07-27' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess -# -# Please send patches to . - - -# The "shellcheck disable" line above the timestamp inhibits complaints -# about features and limitations of the classic Bourne shell that were -# superseded or lifted in POSIX. However, this script identifies a wide -# variety of pre-POSIX systems that do not have POSIX shells at all, and -# even some reasonably current systems (Solaris 10 as case-in-point) still -# have a pre-POSIX /bin/sh. - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system '$me' is run on. - -Options: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2024 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try '$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -# Just in case it came from the environment. -GUESS= - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still -# use 'HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -tmp= -# shellcheck disable=SC2172 -trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 - -set_cc_for_build() { - # prevent multiple calls if $tmp is already set - test "$tmp" && return 0 - : "${TMPDIR=/tmp}" - # shellcheck disable=SC2039,SC3028 - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } - dummy=$tmp/dummy - case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in - ,,) echo "int x;" > "$dummy.c" - for driver in cc gcc c17 c99 c89 ; do - if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD=$driver - break - fi - done - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; - esac -} - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if test -f /.attbin/uname ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case $UNAME_SYSTEM in -Linux|GNU|GNU/*) - LIBC=unknown - - set_cc_for_build - cat <<-EOF > "$dummy.c" - #if defined(__ANDROID__) - LIBC=android - #else - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #elif defined(__GLIBC__) - LIBC=gnu - #elif defined(__LLVM_LIBC__) - LIBC=llvm - #else - #include - /* First heuristic to detect musl libc. */ - #ifdef __DEFINED_va_list - LIBC=musl - #endif - #endif - #endif - EOF - cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` - eval "$cc_set_libc" - - # Second heuristic to detect musl libc. - if [ "$LIBC" = unknown ] && - command -v ldd >/dev/null && - ldd --version 2>&1 | grep -q ^musl; then - LIBC=musl - fi - - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - if [ "$LIBC" = unknown ]; then - LIBC=gnu - fi - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ - /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ - echo unknown)` - case $UNAME_MACHINE_ARCH in - aarch64eb) machine=aarch64_be-unknown ;; - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown - ;; - *) machine=$UNAME_MACHINE_ARCH-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently (or will in the future) and ABI. - case $UNAME_MACHINE_ARCH in - earm*) - os=netbsdelf - ;; - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # Determine ABI tags. - case $UNAME_MACHINE_ARCH in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case $UNAME_VERSION in - Debian*) - release='-gnu' - ;; - *) - release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - GUESS=$machine-${os}${release}${abi-} - ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE - ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE - ;; - *:SecBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` - GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE - ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE - ;; - *:MidnightBSD:*:*) - GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE - ;; - *:ekkoBSD:*:*) - GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE - ;; - *:SolidBSD:*:*) - GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE - ;; - *:OS108:*:*) - GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE - ;; - macppc:MirBSD:*:*) - GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE - ;; - *:MirBSD:*:*) - GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE - ;; - *:Sortix:*:*) - GUESS=$UNAME_MACHINE-unknown-sortix - ;; - *:Twizzler:*:*) - GUESS=$UNAME_MACHINE-unknown-twizzler - ;; - *:Redox:*:*) - GUESS=$UNAME_MACHINE-unknown-redox - ;; - mips:OSF1:*.*) - GUESS=mips-dec-osf1 - ;; - alpha:OSF1:*:*) - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - trap '' 0 - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case $ALPHA_CPU_TYPE in - "EV4 (21064)") - UNAME_MACHINE=alpha ;; - "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; - "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; - "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; - "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; - "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; - "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; - "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; - "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; - "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; - "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; - "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - GUESS=$UNAME_MACHINE-dec-osf$OSF_REL - ;; - Amiga*:UNIX_System_V:4.0:*) - GUESS=m68k-unknown-sysv4 - ;; - *:[Aa]miga[Oo][Ss]:*:*) - GUESS=$UNAME_MACHINE-unknown-amigaos - ;; - *:[Mm]orph[Oo][Ss]:*:*) - GUESS=$UNAME_MACHINE-unknown-morphos - ;; - *:OS/390:*:*) - GUESS=i370-ibm-openedition - ;; - *:z/VM:*:*) - GUESS=s390-ibm-zvmoe - ;; - *:OS400:*:*) - GUESS=powerpc-ibm-os400 - ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - GUESS=arm-acorn-riscix$UNAME_RELEASE - ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - GUESS=arm-unknown-riscos - ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - GUESS=hppa1.1-hitachi-hiuxmpp - ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - case `(/bin/universe) 2>/dev/null` in - att) GUESS=pyramid-pyramid-sysv3 ;; - *) GUESS=pyramid-pyramid-bsd ;; - esac - ;; - NILE*:*:*:dcosx) - GUESS=pyramid-pyramid-svr4 - ;; - DRS?6000:unix:4.0:6*) - GUESS=sparc-icl-nx6 - ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) GUESS=sparc-icl-nx7 ;; - esac - ;; - s390x:SunOS:*:*) - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` - GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL - ;; - sun4H:SunOS:5.*:*) - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` - GUESS=sparc-hal-solaris2$SUN_REL - ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` - GUESS=sparc-sun-solaris2$SUN_REL - ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - GUESS=i386-pc-auroraux$UNAME_RELEASE - ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - set_cc_for_build - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if test "$CC_FOR_BUILD" != no_compiler_found; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` - GUESS=$SUN_ARCH-pc-solaris2$SUN_REL - ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` - GUESS=sparc-sun-solaris3$SUN_REL - ;; - sun4*:SunOS:*:*) - case `/usr/bin/arch -k` in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like '4.1.3-JL'. - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` - GUESS=sparc-sun-sunos$SUN_REL - ;; - sun3*:SunOS:*:*) - GUESS=m68k-sun-sunos$UNAME_RELEASE - ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case `/bin/arch` in - sun3) - GUESS=m68k-sun-sunos$UNAME_RELEASE - ;; - sun4) - GUESS=sparc-sun-sunos$UNAME_RELEASE - ;; - esac - ;; - aushp:SunOS:*:*) - GUESS=sparc-auspex-sunos$UNAME_RELEASE - ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - GUESS=m68k-atari-mint$UNAME_RELEASE - ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - GUESS=m68k-atari-mint$UNAME_RELEASE - ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - GUESS=m68k-atari-mint$UNAME_RELEASE - ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - GUESS=m68k-milan-mint$UNAME_RELEASE - ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - GUESS=m68k-hades-mint$UNAME_RELEASE - ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - GUESS=m68k-unknown-mint$UNAME_RELEASE - ;; - m68k:machten:*:*) - GUESS=m68k-apple-machten$UNAME_RELEASE - ;; - powerpc:machten:*:*) - GUESS=powerpc-apple-machten$UNAME_RELEASE - ;; - RISC*:Mach:*:*) - GUESS=mips-dec-mach_bsd4.3 - ;; - RISC*:ULTRIX:*:*) - GUESS=mips-dec-ultrix$UNAME_RELEASE - ;; - VAX*:ULTRIX*:*:*) - GUESS=vax-dec-ultrix$UNAME_RELEASE - ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - GUESS=clipper-intergraph-clix$UNAME_RELEASE - ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && - dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`"$dummy" "$dummyarg"` && - { echo "$SYSTEM_NAME"; exit; } - GUESS=mips-mips-riscos$UNAME_RELEASE - ;; - Motorola:PowerMAX_OS:*:*) - GUESS=powerpc-motorola-powermax - ;; - Motorola:*:4.3:PL8-*) - GUESS=powerpc-harris-powermax - ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - GUESS=powerpc-harris-powermax - ;; - Night_Hawk:Power_UNIX:*:*) - GUESS=powerpc-harris-powerunix - ;; - m88k:CX/UX:7*:*) - GUESS=m88k-harris-cxux7 - ;; - m88k:*:4*:R4*) - GUESS=m88k-motorola-sysv4 - ;; - m88k:*:3*:R3*) - GUESS=m88k-motorola-sysv3 - ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 - then - if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ - test "$TARGET_BINARY_INTERFACE"x = x - then - GUESS=m88k-dg-dgux$UNAME_RELEASE - else - GUESS=m88k-dg-dguxbcs$UNAME_RELEASE - fi - else - GUESS=i586-dg-dgux$UNAME_RELEASE - fi - ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - GUESS=m88k-dolphin-sysv3 - ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - GUESS=m88k-motorola-sysv3 - ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - GUESS=m88k-tektronix-sysv3 - ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - GUESS=m68k-tektronix-bsd - ;; - *:IRIX*:*:*) - IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` - GUESS=mips-sgi-irix$IRIX_REL - ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id - ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - GUESS=i386-ibm-aix - ;; - ia64:AIX:*:*) - if test -x /usr/bin/oslevel ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=$UNAME_VERSION.$UNAME_RELEASE - fi - GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV - ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" - #include - - int - main () - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` - then - GUESS=$SYSTEM_NAME - else - GUESS=rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - GUESS=rs6000-ibm-aix3.2.4 - else - GUESS=rs6000-ibm-aix3.2 - fi - ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if test -x /usr/bin/lslpp ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV=$UNAME_VERSION.$UNAME_RELEASE - fi - GUESS=$IBM_ARCH-ibm-aix$IBM_REV - ;; - *:AIX:*:*) - GUESS=rs6000-ibm-aix - ;; - ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) - GUESS=romp-ibm-bsd4.4 - ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to - ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - GUESS=rs6000-bull-bosx - ;; - DPX/2?00:B.O.S.:*:*) - GUESS=m68k-bull-sysv3 - ;; - 9000/[34]??:4.3bsd:1.*:*) - GUESS=m68k-hp-bsd - ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - GUESS=m68k-hp-bsd4.4 - ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` - case $UNAME_MACHINE in - 9000/31?) HP_ARCH=m68000 ;; - 9000/[34]??) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if test -x /usr/bin/getconf; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case $sc_cpu_version in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case $sc_kernel_bits in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 - esac ;; - esac - fi - if test "$HP_ARCH" = ""; then - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" - - #define _HPUX_SOURCE - #include - #include - - int - main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if test "$HP_ARCH" = hppa2.0w - then - set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH=hppa2.0w - else - HP_ARCH=hppa64 - fi - fi - GUESS=$HP_ARCH-hp-hpux$HPUX_REV - ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` - GUESS=ia64-hp-hpux$HPUX_REV - ;; - 3050*:HI-UX:*:*) - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && - { echo "$SYSTEM_NAME"; exit; } - GUESS=unknown-hitachi-hiuxwe2 - ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) - GUESS=hppa1.1-hp-bsd - ;; - 9000/8??:4.3bsd:*:*) - GUESS=hppa1.0-hp-bsd - ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - GUESS=hppa1.0-hp-mpeix - ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) - GUESS=hppa1.1-hp-osf - ;; - hp8??:OSF1:*:*) - GUESS=hppa1.0-hp-osf - ;; - i*86:OSF1:*:*) - if test -x /usr/sbin/sysversion ; then - GUESS=$UNAME_MACHINE-unknown-osf1mk - else - GUESS=$UNAME_MACHINE-unknown-osf1 - fi - ;; - parisc*:Lites*:*:*) - GUESS=hppa1.1-hp-lites - ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - GUESS=c1-convex-bsd - ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - GUESS=c34-convex-bsd - ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - GUESS=c38-convex-bsd - ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - GUESS=c4-convex-bsd - ;; - CRAY*Y-MP:*:*:*) - CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` - GUESS=ymp-cray-unicos$CRAY_REL - ;; - CRAY*[A-Z]90:*:*:*) - echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` - GUESS=t90-cray-unicos$CRAY_REL - ;; - CRAY*T3E:*:*:*) - CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` - GUESS=alphaev5-cray-unicosmk$CRAY_REL - ;; - CRAY*SV1:*:*:*) - CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` - GUESS=sv1-cray-unicos$CRAY_REL - ;; - *:UNICOS/mp:*:*) - CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` - GUESS=craynv-cray-unicosmp$CRAY_REL - ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` - GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} - ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} - ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE - ;; - sparc*:BSD/OS:*:*) - GUESS=sparc-unknown-bsdi$UNAME_RELEASE - ;; - *:BSD/OS:*:*) - GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE - ;; - arm:FreeBSD:*:*) - UNAME_PROCESSOR=`uname -p` - set_cc_for_build - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` - GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi - else - FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` - GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf - fi - ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`uname -p` - case $UNAME_PROCESSOR in - amd64) - UNAME_PROCESSOR=x86_64 ;; - i386) - UNAME_PROCESSOR=i586 ;; - esac - FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` - GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL - ;; - i*:CYGWIN*:*) - GUESS=$UNAME_MACHINE-pc-cygwin - ;; - *:MINGW64*:*) - GUESS=$UNAME_MACHINE-pc-mingw64 - ;; - *:MINGW*:*) - GUESS=$UNAME_MACHINE-pc-mingw32 - ;; - *:MSYS*:*) - GUESS=$UNAME_MACHINE-pc-msys - ;; - i*:PW*:*) - GUESS=$UNAME_MACHINE-pc-pw32 - ;; - *:SerenityOS:*:*) - GUESS=$UNAME_MACHINE-pc-serenity - ;; - *:Interix*:*) - case $UNAME_MACHINE in - x86) - GUESS=i586-pc-interix$UNAME_RELEASE - ;; - authenticamd | genuineintel | EM64T) - GUESS=x86_64-unknown-interix$UNAME_RELEASE - ;; - IA64) - GUESS=ia64-unknown-interix$UNAME_RELEASE - ;; - esac ;; - i*:UWIN*:*) - GUESS=$UNAME_MACHINE-pc-uwin - ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - GUESS=x86_64-pc-cygwin - ;; - prep*:SunOS:5.*:*) - SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` - GUESS=powerpcle-unknown-solaris2$SUN_REL - ;; - *:GNU:*:*) - # the GNU system - GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` - GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` - GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL - ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` - GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` - GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC - ;; - x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) - GUESS="$UNAME_MACHINE-pc-managarm-mlibc" - ;; - *:[Mm]anagarm:*:*) - GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" - ;; - *:Minix:*:*) - GUESS=$UNAME_MACHINE-unknown-minix - ;; - aarch64:Linux:*:*) - set_cc_for_build - CPU=$UNAME_MACHINE - LIBCABI=$LIBC - if test "$CC_FOR_BUILD" != no_compiler_found; then - ABI=64 - sed 's/^ //' << EOF > "$dummy.c" - #ifdef __ARM_EABI__ - #ifdef __ARM_PCS_VFP - ABI=eabihf - #else - ABI=eabi - #endif - #endif -EOF - cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` - eval "$cc_set_abi" - case $ABI in - eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;; - esac - fi - GUESS=$CPU-unknown-linux-$LIBCABI - ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - arm*:Linux:*:*) - set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi - else - GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf - fi - fi - ;; - avr32*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - cris:Linux:*:*) - GUESS=$UNAME_MACHINE-axis-linux-$LIBC - ;; - crisv32:Linux:*:*) - GUESS=$UNAME_MACHINE-axis-linux-$LIBC - ;; - e2k:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - frv:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - hexagon:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - i*86:Linux:*:*) - GUESS=$UNAME_MACHINE-pc-linux-$LIBC - ;; - ia64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - k1om:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - kvx:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - kvx:cos:*:*) - GUESS=$UNAME_MACHINE-unknown-cos - ;; - kvx:mbr:*:*) - GUESS=$UNAME_MACHINE-unknown-mbr - ;; - loongarch32:Linux:*:* | loongarch64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - m32r*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - m68*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - mips:Linux:*:* | mips64:Linux:*:*) - set_cc_for_build - IS_GLIBC=0 - test x"${LIBC}" = xgnu && IS_GLIBC=1 - sed 's/^ //' << EOF > "$dummy.c" - #undef CPU - #undef mips - #undef mipsel - #undef mips64 - #undef mips64el - #if ${IS_GLIBC} && defined(_ABI64) - LIBCABI=gnuabi64 - #else - #if ${IS_GLIBC} && defined(_ABIN32) - LIBCABI=gnuabin32 - #else - LIBCABI=${LIBC} - #endif - #endif - - #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 - CPU=mipsisa64r6 - #else - #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 - CPU=mipsisa32r6 - #else - #if defined(__mips64) - CPU=mips64 - #else - CPU=mips - #endif - #endif - #endif - - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - MIPS_ENDIAN=el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - MIPS_ENDIAN= - #else - MIPS_ENDIAN= - #endif - #endif -EOF - cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` - eval "$cc_set_vars" - test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } - ;; - mips64el:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - openrisc*:Linux:*:*) - GUESS=or1k-unknown-linux-$LIBC - ;; - or32:Linux:*:* | or1k*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - padre:Linux:*:*) - GUESS=sparc-unknown-linux-$LIBC - ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - GUESS=hppa64-unknown-linux-$LIBC - ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; - PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; - *) GUESS=hppa-unknown-linux-$LIBC ;; - esac - ;; - ppc64:Linux:*:*) - GUESS=powerpc64-unknown-linux-$LIBC - ;; - ppc:Linux:*:*) - GUESS=powerpc-unknown-linux-$LIBC - ;; - ppc64le:Linux:*:*) - GUESS=powerpc64le-unknown-linux-$LIBC - ;; - ppcle:Linux:*:*) - GUESS=powerpcle-unknown-linux-$LIBC - ;; - riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - s390:Linux:*:* | s390x:Linux:*:*) - GUESS=$UNAME_MACHINE-ibm-linux-$LIBC - ;; - sh64*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - sh*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - tile*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - vax:Linux:*:*) - GUESS=$UNAME_MACHINE-dec-linux-$LIBC - ;; - x86_64:Linux:*:*) - set_cc_for_build - CPU=$UNAME_MACHINE - LIBCABI=$LIBC - if test "$CC_FOR_BUILD" != no_compiler_found; then - ABI=64 - sed 's/^ //' << EOF > "$dummy.c" - #ifdef __i386__ - ABI=x86 - #else - #ifdef __ILP32__ - ABI=x32 - #endif - #endif -EOF - cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` - eval "$cc_set_abi" - case $ABI in - x86) CPU=i686 ;; - x32) LIBCABI=${LIBC}x32 ;; - esac - fi - GUESS=$CPU-pc-linux-$LIBCABI - ;; - xtensa*:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC - ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - GUESS=i386-sequent-sysv4 - ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION - ;; - i*86:OS/2:*:*) - # If we were able to find 'uname', then EMX Unix compatibility - # is probably installed. - GUESS=$UNAME_MACHINE-pc-os2-emx - ;; - i*86:XTS-300:*:STOP) - GUESS=$UNAME_MACHINE-unknown-stop - ;; - i*86:atheos:*:*) - GUESS=$UNAME_MACHINE-unknown-atheos - ;; - i*86:syllable:*:*) - GUESS=$UNAME_MACHINE-pc-syllable - ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - GUESS=i386-unknown-lynxos$UNAME_RELEASE - ;; - i*86:*DOS:*:*) - GUESS=$UNAME_MACHINE-pc-msdosdjgpp - ;; - i*86:*:4.*:*) - UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL - else - GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL - fi - ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL - else - GUESS=$UNAME_MACHINE-pc-sysv32 - fi - ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that - # this is a cross-build. - GUESS=i586-pc-msdosdjgpp - ;; - Intel:Mach:3*:*) - GUESS=i386-pc-mach3 - ;; - paragon:*:*:*) - GUESS=i860-intel-osf1 - ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 - fi - ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - GUESS=m68010-convergent-sysv - ;; - mc68k:UNIX:SYSTEM5:3.51m) - GUESS=m68k-convergent-sysv - ;; - M680?0:D-NIX:5.3:*) - GUESS=m68k-diab-dnix - ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - GUESS=m68k-unknown-lynxos$UNAME_RELEASE - ;; - mc68030:UNIX_System_V:4.*:*) - GUESS=m68k-atari-sysv4 - ;; - TSUNAMI:LynxOS:2.*:*) - GUESS=sparc-unknown-lynxos$UNAME_RELEASE - ;; - rs6000:LynxOS:2.*:*) - GUESS=rs6000-unknown-lynxos$UNAME_RELEASE - ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - GUESS=powerpc-unknown-lynxos$UNAME_RELEASE - ;; - SM[BE]S:UNIX_SV:*:*) - GUESS=mips-dde-sysv$UNAME_RELEASE - ;; - RM*:ReliantUNIX-*:*:*) - GUESS=mips-sni-sysv4 - ;; - RM*:SINIX-*:*:*) - GUESS=mips-sni-sysv4 - ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - GUESS=$UNAME_MACHINE-sni-sysv4 - else - GUESS=ns32k-sni-sysv - fi - ;; - PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort - # says - GUESS=i586-unisys-sysv4 - ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - GUESS=hppa1.1-stratus-sysv4 - ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - GUESS=i860-stratus-sysv4 - ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - GUESS=$UNAME_MACHINE-stratus-vos - ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - GUESS=hppa1.1-stratus-vos - ;; - mc68*:A/UX:*:*) - GUESS=m68k-apple-aux$UNAME_RELEASE - ;; - news*:NEWS-OS:6*:*) - GUESS=mips-sony-newsos6 - ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if test -d /usr/nec; then - GUESS=mips-nec-sysv$UNAME_RELEASE - else - GUESS=mips-unknown-sysv$UNAME_RELEASE - fi - ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - GUESS=powerpc-be-beos - ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - GUESS=powerpc-apple-beos - ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - GUESS=i586-pc-beos - ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - GUESS=i586-pc-haiku - ;; - ppc:Haiku:*:*) # Haiku running on Apple PowerPC - GUESS=powerpc-apple-haiku - ;; - *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) - GUESS=$UNAME_MACHINE-unknown-haiku - ;; - SX-4:SUPER-UX:*:*) - GUESS=sx4-nec-superux$UNAME_RELEASE - ;; - SX-5:SUPER-UX:*:*) - GUESS=sx5-nec-superux$UNAME_RELEASE - ;; - SX-6:SUPER-UX:*:*) - GUESS=sx6-nec-superux$UNAME_RELEASE - ;; - SX-7:SUPER-UX:*:*) - GUESS=sx7-nec-superux$UNAME_RELEASE - ;; - SX-8:SUPER-UX:*:*) - GUESS=sx8-nec-superux$UNAME_RELEASE - ;; - SX-8R:SUPER-UX:*:*) - GUESS=sx8r-nec-superux$UNAME_RELEASE - ;; - SX-ACE:SUPER-UX:*:*) - GUESS=sxace-nec-superux$UNAME_RELEASE - ;; - Power*:Rhapsody:*:*) - GUESS=powerpc-apple-rhapsody$UNAME_RELEASE - ;; - *:Rhapsody:*:*) - GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE - ;; - arm64:Darwin:*:*) - GUESS=aarch64-apple-darwin$UNAME_RELEASE - ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` - case $UNAME_PROCESSOR in - unknown) UNAME_PROCESSOR=powerpc ;; - esac - if command -v xcode-select > /dev/null 2> /dev/null && \ - ! xcode-select --print-path > /dev/null 2> /dev/null ; then - # Avoid executing cc if there is no toolchain installed as - # cc will be a stub that puts up a graphical alert - # prompting the user to install developer tools. - CC_FOR_BUILD=no_compiler_found - else - set_cc_for_build - fi - if test "$CC_FOR_BUILD" != no_compiler_found; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # uname -m returns i386 or x86_64 - UNAME_PROCESSOR=$UNAME_MACHINE - fi - GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE - ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE - ;; - *:QNX:*:4*) - GUESS=i386-pc-qnx - ;; - NEO-*:NONSTOP_KERNEL:*:*) - GUESS=neo-tandem-nsk$UNAME_RELEASE - ;; - NSE-*:NONSTOP_KERNEL:*:*) - GUESS=nse-tandem-nsk$UNAME_RELEASE - ;; - NSR-*:NONSTOP_KERNEL:*:*) - GUESS=nsr-tandem-nsk$UNAME_RELEASE - ;; - NSV-*:NONSTOP_KERNEL:*:*) - GUESS=nsv-tandem-nsk$UNAME_RELEASE - ;; - NSX-*:NONSTOP_KERNEL:*:*) - GUESS=nsx-tandem-nsk$UNAME_RELEASE - ;; - *:NonStop-UX:*:*) - GUESS=mips-compaq-nonstopux - ;; - BS2000:POSIX*:*:*) - GUESS=bs2000-siemens-sysv - ;; - DS/*:UNIX_System_V:*:*) - GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE - ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "${cputype-}" = 386; then - UNAME_MACHINE=i386 - elif test "x${cputype-}" != x; then - UNAME_MACHINE=$cputype - fi - GUESS=$UNAME_MACHINE-unknown-plan9 - ;; - *:TOPS-10:*:*) - GUESS=pdp10-unknown-tops10 - ;; - *:TENEX:*:*) - GUESS=pdp10-unknown-tenex - ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - GUESS=pdp10-dec-tops20 - ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - GUESS=pdp10-xkl-tops20 - ;; - *:TOPS-20:*:*) - GUESS=pdp10-unknown-tops20 - ;; - *:ITS:*:*) - GUESS=pdp10-unknown-its - ;; - SEI:*:*:SEIUX) - GUESS=mips-sei-seiux$UNAME_RELEASE - ;; - *:DragonFly:*:*) - DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` - GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL - ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case $UNAME_MACHINE in - A*) GUESS=alpha-dec-vms ;; - I*) GUESS=ia64-dec-vms ;; - V*) GUESS=vax-dec-vms ;; - esac ;; - *:XENIX:*:SysV) - GUESS=i386-pc-xenix - ;; - i*86:skyos:*:*) - SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` - GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL - ;; - i*86:rdos:*:*) - GUESS=$UNAME_MACHINE-pc-rdos - ;; - i*86:Fiwix:*:*) - GUESS=$UNAME_MACHINE-pc-fiwix - ;; - *:AROS:*:*) - GUESS=$UNAME_MACHINE-unknown-aros - ;; - x86_64:VMkernel:*:*) - GUESS=$UNAME_MACHINE-unknown-esx - ;; - amd64:Isilon\ OneFS:*:*) - GUESS=x86_64-unknown-onefs - ;; - *:Unleashed:*:*) - GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE - ;; - *:Ironclad:*:*) - GUESS=$UNAME_MACHINE-unknown-ironclad - ;; -esac - -# Do we have a guess based on uname results? -if test "x$GUESS" != x; then - echo "$GUESS" - exit -fi - -# No uname command or uname output not recognized. -set_cc_for_build -cat > "$dummy.c" < -#include -#endif -#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) -#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) -#include -#if defined(_SIZE_T_) || defined(SIGLOST) -#include -#endif -#endif -#endif -int -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); -#endif - -#if defined (vax) -#if !defined (ultrix) -#include -#if defined (BSD) -#if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -#else -#if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -#else - printf ("vax-dec-bsd\n"); exit (0); -#endif -#endif -#else - printf ("vax-dec-bsd\n"); exit (0); -#endif -#else -#if defined(_SIZE_T_) || defined(SIGLOST) - struct utsname un; - uname (&un); - printf ("vax-dec-ultrix%s\n", un.release); exit (0); -#else - printf ("vax-dec-ultrix\n"); exit (0); -#endif -#endif -#endif -#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) -#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) -#if defined(_SIZE_T_) || defined(SIGLOST) - struct utsname *un; - uname (&un); - printf ("mips-dec-ultrix%s\n", un.release); exit (0); -#else - printf ("mips-dec-ultrix\n"); exit (0); -#endif -#endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. -test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } - -echo "$0: unable to guess system type" >&2 - -case $UNAME_MACHINE:$UNAME_SYSTEM in - mips:Linux | mips64:Linux) - # If we got here on MIPS GNU/Linux, output extra information. - cat >&2 <&2 <&2 </dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = "$UNAME_MACHINE" -UNAME_RELEASE = "$UNAME_RELEASE" -UNAME_SYSTEM = "$UNAME_SYSTEM" -UNAME_VERSION = "$UNAME_VERSION" -EOF -fi - -exit 1 - -# Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/graf2d/asimage/src/libAfterImage/config.h.in b/graf2d/asimage/src/libAfterImage/config.h.in deleted file mode 100644 index 6b376e9e697c7..0000000000000 --- a/graf2d/asimage/src/libAfterImage/config.h.in +++ /dev/null @@ -1,179 +0,0 @@ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if memory allocation logging and debugging is desired */ -#undef DEBUG_ALLOCS - -/* Define if libAfterBase is available */ -#undef HAVE_AFTERBASE - -/* Define if using builtin libjpeg */ -#undef HAVE_BUILTIN_JPEG - -/* Define if using builtin libpng */ -#undef HAVE_BUILTIN_PNG - -/* Define if using builtin libungif */ -#undef HAVE_BUILTIN_UNGIF - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_ERRNO_H - -/* Define if libFreeType is available */ -#undef HAVE_FREETYPE - -/* Define if libFreeType has freetype.h in freetype/ */ -#undef HAVE_FREETYPE_FREETYPE - -/* Define to 1 if you have the header file. */ -#define HAVE_FT2BUILD_H - -/* Define if libgif/ungif is available */ -#undef HAVE_GIF - -/* Support for OpenGL extention */ -#undef HAVE_GLX - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define if libjpeg is available */ -#undef HAVE_JPEG - -/* Define if support for XPM images should be through libXpm */ -#undef HAVE_LIBXPM - -/* Define if support for XPM images should be through libXpm library in Xlib - */ -#undef HAVE_LIBXPM_X11 - -/* Define to 1 if the system has the type `long long'. */ -#undef HAVE_LONG_LONG - -/* Define to 1 if you have the header file. */ -#undef HAVE_MALLOC_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define if CPU supports MMX instructions */ -#undef HAVE_MMX - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define if libpng is available */ -#undef HAVE_PNG - -/* We always use function prototypes - not supporting old compilers */ -#undef HAVE_PROTOTYPES - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDDEF_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* librsvg v.2.0 or higher is available */ -#undef HAVE_SVG - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_DIRENT_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_WAIT_H - -/* Define if libtiff is available */ -#undef HAVE_TIFF - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define if support for XPM images is desired */ -#undef HAVE_XPM - -/* Define to 1 if you have the header file. */ -#undef HAVE_ZLIB_H - -/* Define if locale support in X is needed */ -#undef I18N - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Support for shaped windows */ -#undef SHAPE - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 if you can safely include both and . */ -#undef TIME_WITH_SYS_TIME - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#undef WORDS_BIGENDIAN - -/* Define if support for shared memory XImages is available */ -#undef XSHMIMAGE - -/* Define to 1 if the X Window System is missing or not being used. */ -#undef X_DISPLAY_MISSING - -/* Define to 1 if type `char' is unsigned and you are not using gcc. */ -#ifndef __CHAR_UNSIGNED__ -# undef __CHAR_UNSIGNED__ -#endif - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif diff --git a/graf2d/asimage/src/libAfterImage/config.sub b/graf2d/asimage/src/libAfterImage/config.sub deleted file mode 100755 index 6d2e94c8bf9ea..0000000000000 --- a/graf2d/asimage/src/libAfterImage/config.sub +++ /dev/null @@ -1,1807 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2015 Free Software Foundation, Inc. - -timestamp='2015-01-01' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2015 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/graf2d/asimage/src/libAfterImage/configure b/graf2d/asimage/src/libAfterImage/configure deleted file mode 100755 index a3d67ddc9a1e6..0000000000000 --- a/graf2d/asimage/src/libAfterImage/configure +++ /dev/null @@ -1,10614 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for libAfterImage 1.20. -# -# Report bugs to . -# -# Copyright (C) 2003 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -exec 6>&1 - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_config_libobj_dir=. -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} - -# Identity of this package. -PACKAGE_NAME='libAfterImage' -PACKAGE_TARNAME='libAfterImage.tar' -PACKAGE_VERSION='1.20' -PACKAGE_STRING='libAfterImage 1.20' -PACKAGE_BUGREPORT='as-bugs@afterstep.org' - -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#if HAVE_SYS_TYPES_H -# include -#endif -#if HAVE_SYS_STAT_H -# include -#endif -#if STDC_HEADERS -# include -# include -#else -# if HAVE_STDLIB_H -# include -# endif -#endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H -# include -# endif -# include -#endif -#if HAVE_STRINGS_H -# include -#endif -#if HAVE_INTTYPES_H -# include -#else -# if HAVE_STDINT_H -# include -# endif -#endif -#if HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LN_S build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL INSTALL_PROGRAM INSTALL_DATA INSTALL_LIB RANLIB RM MV CP MKDIR PERL FIND XARGS LDCONFIG LEX LEXLIB YACC INSTALL_SCRIPT ac_ct_RANLIB MMX_CFLAGS CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS EGREP XPM_CFLAGS JPEG_CFLAGS PNG_CFLAGS GIF_CFLAGS TIFF_CFLAGS PKG_CONFIG ac_pt_PKG_CONFIG SVG_CFLAGS SVG_LIBS TTF_INCLUDES JPEG_OBJS ZLIB_OBJS PNG_OBJS UNGIF_OBJS AFTERIMAGE_LIBS_EXTERNAL AFTERBASE_INCS_PATH USE_DEFAULT_AFTERBASE HAVE_AFTERBASE_FLAG AFTERBASE_C have_afterbase AFTERIMAGE_APPS_LIBS AFTERIMAGE_TEST_LIBS AFTERIMAGE_LIB_LIBS afterimage_x_support AFTERIMAGE_LIBS image_format version version_major lib_name lib_file_name with_locale user_ldflags x_libs LIBPROG LIBINSTALL DEFINE_XLOCALE APPSDEPS LIBOBJS LTLIBOBJS' -ac_subst_files='LIBAFTERIMAGEFILES' - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -ac_prev= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_option in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "enable_$ac_feature='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "with_$ac_package='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi -fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS -ac_env_CPP_set=${CPP+set} -ac_env_CPP_value=$CPP -ac_cv_env_CPP_set=${CPP+set} -ac_cv_env_CPP_value=$CPP -ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} -ac_env_PKG_CONFIG_value=$PKG_CONFIG -ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} -ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG -ac_env_SVG_CFLAGS_set=${SVG_CFLAGS+set} -ac_env_SVG_CFLAGS_value=$SVG_CFLAGS -ac_cv_env_SVG_CFLAGS_set=${SVG_CFLAGS+set} -ac_cv_env_SVG_CFLAGS_value=$SVG_CFLAGS -ac_env_SVG_LIBS_set=${SVG_LIBS+set} -ac_env_SVG_LIBS_value=$SVG_LIBS -ac_cv_env_SVG_LIBS_set=${SVG_LIBS+set} -ac_cv_env_SVG_LIBS_value=$SVG_LIBS - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures libAfterImage 1.20 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -_ACEOF - - cat <<_ACEOF -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] -_ACEOF - - cat <<\_ACEOF - -X features: - --x-includes=DIR X include files are in DIR - --x-libraries=DIR X library files are in DIR - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of libAfterImage 1.20:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-i18n support I18N no - --enable-xlocale using X_LOCALE no - --enable-staticlibs enable linking to libAfterImage statically yes - --enable-sharedlibs enable linking to libAfterImage dynamically no - --enable-gdb add gdb symbols (-g) (for debugging) no - --enable-warn turn on more compiler warnings (for debugging) no - --enable-gprof add gprof symbols (-pg) (for debugging) no - --enable-audit memory usage audit (for debugging) no - --enable-shmimage enable usage of MIT shared memory extention for image transfer no - --enable-shaping enable usage of MIT shaped windows extention yes - --enable-glx enable usage of GLX extention no - --enable-mmx-optimization enable utilization of MMX instruction set to speed up imaging operations yes - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-locale=LOCALE locale name you want to use - --with-jpeg support JPEG image format yes - --with-jpeg-includes=DIR use JPEG includes in DIR - --with-builtin-jpeg use included JPEG library no - --with-png support PNG image format yes - --with-png-includes=DIR use PNG includes in DIR - --with-builtin-png use included PNG library no - --with-builtin-zlib use included libZ library (needed for PNG) no - --with-tiff support TIFF image format yes - --with-tiff-includes=DIR use TIFF includes in DIR - --with-svg support SVG image format via librsvg yes - --with-xpm support XPM image format yes - --with-ungif support Uncompressed GIF image format using libungif no - --with-gif support GIF image format using libgif no - --with-gif-includes=DIR use GIF includes in DIR - --with-builtin-gif support Uncompressed GIF image format using builtin libgif yes - --with-ttf support True Type Fonts via FreeType library yes - --with-ttf-includes=DIR use FreeType includes in DIR - --with-afterbase use libAfterBase library of basic functionality yes - --with-afterbase-includes=DIR use libAfterBase includes in DIR - --with-x use the X Window System - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have - headers in a nonstandard directory - CPP C preprocessor - PKG_CONFIG path to pkg-config utility - SVG_CFLAGS C compiler flags for SVG, overriding pkg-config - SVG_LIBS linker flags for SVG, overriding pkg-config - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -_ACEOF -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - ac_popdir=`pwd` - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd "$ac_popdir" - done -fi - -test -n "$ac_init_help" && exit 0 -if $ac_init_version; then - cat <<\_ACEOF -libAfterImage configure 1.20 -generated by GNU Autoconf 2.59 - -Copyright (C) 2003 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit 0 -fi -exec 5>config.log -cat >&5 <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by libAfterImage $as_me 1.20, which was -generated by GNU Autoconf 2.59. Invocation command line was - - $ $0 $@ - -_ACEOF -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_sep= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -{ - (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) - sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; - *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - sed "/^$/d" confdefs.h | sort - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status - ' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo >confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . $cache_file;; - *) . ./$cache_file;; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ac_config_headers="$ac_config_headers config.h:config.h.in" - - -version=$PACKAGE_VERSION -version_major="1" -lib_name="LIBAFTERIMAGE" -lib_file_name=$PACKAGE_NAME - - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -test "x$exec_prefix" = xNONE && exec_prefix="$prefix" -eval "mandir=$mandir" -eval "libdir=$libdir" -eval "includedir=$includedir" - -# Check whether --enable-i18n or --disable-i18n was given. -if test "${enable_i18n+set}" = set; then - enableval="$enable_i18n" - enable_i18n=$enableval -else - enable_i18n="no" -fi; -# Check whether --enable-xlocale or --disable-xlocale was given. -if test "${enable_xlocale+set}" = set; then - enableval="$enable_xlocale" - enable_xlocale=$enableval -else - enable_xlocale="no" -fi; - -# Check whether --with-locale or --without-locale was given. -if test "${with_locale+set}" = set; then - withval="$with_locale" - with_locale=$withval -else - with_locale="" -fi; -# Check whether --enable-staticlibs or --disable-staticlibs was given. -if test "${enable_staticlibs+set}" = set; then - enableval="$enable_staticlibs" - enable_staticlibs=$enableval -else - enable_staticlibs="yes" -fi; -# Check whether --enable-sharedlibs or --disable-sharedlibs was given. -if test "${enable_sharedlibs+set}" = set; then - enableval="$enable_sharedlibs" - enable_sharedlibs=$enableval -else - enable_sharedlibs="no" -fi; - -# Check whether --enable-gdb or --disable-gdb was given. -if test "${enable_gdb+set}" = set; then - enableval="$enable_gdb" - enable_gdb=$enableval -else - enable_gdb="no" -fi; -# Check whether --enable-warn or --disable-warn was given. -if test "${enable_warn+set}" = set; then - enableval="$enable_warn" - enable_warn=$enableval -else - enable_warn="no" -fi; -# Check whether --enable-gprof or --disable-gprof was given. -if test "${enable_gprof+set}" = set; then - enableval="$enable_gprof" - enable_gprof=$enableval -else - enable_gprof="no" -fi; -# Check whether --enable-audit or --disable-audit was given. -if test "${enable_audit+set}" = set; then - enableval="$enable_audit" - enable_audit=$enableval -else - enable_audit="no" -fi; -# Check whether --enable-shmimage or --disable-shmimage was given. -if test "${enable_shmimage+set}" = set; then - enableval="$enable_shmimage" - enable_shmimage=$enableval -else - enable_shmimage="no" -fi; -# Check whether --enable-shaping or --disable-shaping was given. -if test "${enable_shaping+set}" = set; then - enableval="$enable_shaping" - enable_shaping=$enableval -else - enable_shaping="yes" -fi; -# Check whether --enable-glx or --disable-glx was given. -if test "${enable_glx+set}" = set; then - enableval="$enable_glx" - enable_glx=$enableval -else - enable_glx="no" -fi; - -# Check whether --enable-mmx_optimization or --disable-mmx_optimization was given. -if test "${enable_mmx_optimization+set}" = set; then - enableval="$enable_mmx_optimization" - enable_mmx_optimization=$enableval -else - enable_mmx_optimization="yes" -fi; - - -# Check whether --with-jpeg or --without-jpeg was given. -if test "${with_jpeg+set}" = set; then - withval="$with_jpeg" - -fi; - -# Check whether --with-jpeg_includes or --without-jpeg_includes was given. -if test "${with_jpeg_includes+set}" = set; then - withval="$with_jpeg_includes" - jpeg_includes="$withval" -else - jpeg_includes=no -fi; - -# Check whether --with-builtin_jpeg or --without-builtin_jpeg was given. -if test "${with_builtin_jpeg+set}" = set; then - withval="$with_builtin_jpeg" - with_builtin_jpeg="$withval" -else - with_builtin_jpeg=no -fi; - -# Check whether --with-png or --without-png was given. -if test "${with_png+set}" = set; then - withval="$with_png" - -fi; - -# Check whether --with-png_includes or --without-png_includes was given. -if test "${with_png_includes+set}" = set; then - withval="$with_png_includes" - png_includes="$withval" -else - png_includes=no -fi; - -# Check whether --with-builtin_png or --without-builtin_png was given. -if test "${with_builtin_png+set}" = set; then - withval="$with_builtin_png" - with_builtin_png="$withval" -else - with_builtin_png=no -fi; - -# Check whether --with-builtin_zlib or --without-builtin_zlib was given. -if test "${with_builtin_zlib+set}" = set; then - withval="$with_builtin_zlib" - with_builtin_zlib="$withval" -else - with_builtin_zlib=no -fi; - -# Check whether --with-tiff or --without-tiff was given. -if test "${with_tiff+set}" = set; then - withval="$with_tiff" - -fi; - -# Check whether --with-tiff_includes or --without-tiff_includes was given. -if test "${with_tiff_includes+set}" = set; then - withval="$with_tiff_includes" - tiff_includes="$withval" -else - tiff_includes=no -fi; - -# Check whether --with-svg or --without-svg was given. -if test "${with_svg+set}" = set; then - withval="$with_svg" - -fi; - - -# Check whether --with-xpm or --without-xpm was given. -if test "${with_xpm+set}" = set; then - withval="$with_xpm" - -fi; -with_builtin_xpm=$with_xpm - -# Check whether --with-ungif or --without-ungif was given. -if test "${with_ungif+set}" = set; then - withval="$with_ungif" - with_ungif="$withval" -else - with_ungif=no -fi; - -# Check whether --with-gif or --without-gif was given. -if test "${with_gif+set}" = set; then - withval="$with_gif" - with_gif="$withval" -else - with_gif=no -fi; - -# Check whether --with-gif_includes or --without-gif_includes was given. -if test "${with_gif_includes+set}" = set; then - withval="$with_gif_includes" - gif_includes="$withval" -else - gif_includes=no -fi; - -# Check whether --with-builtin_gif or --without-builtin_gif was given. -if test "${with_builtin_gif+set}" = set; then - withval="$with_builtin_gif" - with_builtin_gif="$withval" -else - with_builtin_gif=yes -fi; - - - -# Check whether --with-ttf or --without-ttf was given. -if test "${with_ttf+set}" = set; then - withval="$with_ttf" - -fi; - -# Check whether --with-ttf_includes or --without-ttf_includes was given. -if test "${with_ttf_includes+set}" = set; then - withval="$with_ttf_includes" - ttf_includes="$withval" -else - ttf_includes=no -fi; - - -# Check whether --with-afterbase or --without-afterbase was given. -if test "${with_afterbase+set}" = set; then - withval="$with_afterbase" - with_afterbase="$withval" -else - with_afterbase=yes -fi; - -# Check whether --with-afterbase_includes or --without-afterbase_includes was given. -if test "${with_afterbase_includes+set}" = set; then - withval="$with_afterbase_includes" - afterbase_includes="$withval" -else - afterbase_includes=no -fi; - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; - * ) - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 - -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else - echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&6 -fi - - - -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f $ac_dir/shtool; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 -echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} - { (exit 1); exit 1; }; } -fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. - -# Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } - -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 -build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 -host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -case $host_os in - *cygwin* ) CYGWIN=yes;; - * ) CYGWIN=no;; -esac - -echo "$as_me:$LINENO: checking target system type" >&5 -echo $ECHO_N "checking target system type... $ECHO_C" >&6 -if test "${ac_cv_target+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_target_alias=$target_alias -test "x$ac_cv_target_alias" = "x" && - ac_cv_target_alias=$ac_cv_host_alias -ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_target" >&5 -echo "${ECHO_T}$ac_cv_target" >&6 -target=$ac_cv_target -target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - -RDYNAMIC="-rdynamic" - -case "$target" in - *i?86*OpenUNIX*) - RDYNAMIC="-Wl,-Bexport" - ;; - *i?86*sco*) - RDYNAMIC="-Wl,-Bexport" - ;; - *aix*) - RDYNAMIC="-Wl,-bexpall" - ;; - *i?86*freebsd*) - RDYNAMIC="" - ;; - hppa*) - RDYNAMIC="-Wl,-E" - ;; - i?86*solaris*) - RDYNAMIC="" - ;; - sparc*solaris*) - RDYNAMIC="-Wl,-export-dynamic" - ;; - *-apple-darwin*) - RDYNAMIC="-Wl,-Sn" - ;; - *ppc* | *powerpc*) - RDYNAMIC="" - ;; - *) -esac - -if test "x$CYGWIN" = "xno" -a "x$GCC" = "xyes" ; then - if test -z "`echo $CFLAGS | grep '\-fPIC' 2> /dev/null`" ; then - CFLAGS="$CFLAGS -fPIC" - fi -fi - - -if test "x$FROM_AFTERSTEP_CONFIGURE" = "xyes"; then - - aaa=bbb - - - - - - - - - - - - - - - - - if test "x$have_shmimage" = "xyes"; then - cat >>confdefs.h <<\_ACEOF -#define XSHMIMAGE 1 -_ACEOF - - fi - if test "x$have_shaping" = "xyes"; then - cat >>confdefs.h <<\_ACEOF -#define SHAPE 1 -_ACEOF - - fi - -else - - if test "x$GCC" = "xyes"; then - if test -z "`echo $CFLAGS | grep '\-Wall' 2> /dev/null`" ; then - #CFLAGS="$CFLAGS -Wall" - #rdm No -Wall to silence unused warnings on Ubuntu. - CFLAGS="$CFLAGS" - fi - fi - - - if test "x$enable_gdb" = "xyes"; then - if ! test -n "`echo $CFLAGS' ' | grep '\-g ' 2> /dev/null`" ; then - CFLAGS="$CFLAGS -g" - fi - else - DIRTY_CFLAGS="$CFLAGS" - CFLAGS="-DNO_DEBUG_OUTPUT" - for f in $DIRTY_CFLAGS; do - if test "x$f" != "x-g"; then - CFLAGS="$CFLAGS $f" - fi - done - fi - if test "x$enable_gprof" = "xyes"; then - CFLAGS="$CFLAGS -pg" - LDFLAGS="$LDFLAGS -pg" - fi - if test "x$enable_warn" = "xyes"; then - CFLAGS="$CFLAGS -Wuninitialized -Wwrite-strings -Wcast-qual -Wbad-function-cast -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wconversion -Wcomment -Wcast-align -Wshadow -Wredundant-decls" - fi - # Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - done - done - ;; -esac -done - - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the path is relative. - INSTALL=$ac_install_sh - fi -fi -echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6 - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - - currdir=`pwd` - INSTALL=`echo $INSTALL|sed -e "s|\^\.\.|${currdir}|" -e "s|^autoconf|${currdir}/autoconf|"` - INSTALL_PROGRAM=`echo $INSTALL_PROGRAM|sed -e "s|\^\.\.|${currdir}|" -e "s|^autoconf|${currdir}/autoconf|"` - INSTALL_DATA=`echo $INSTALL_DATA|sed -e "s|\^\.\.|${currdir}|" -e "s|^autoconf|${currdir}/autoconf|"` - INSTALL_LIB=`echo $INSTALL_LIB|sed -e "s|\^\.\.|${currdir}|" -e "s|^autoconf|${currdir}/autoconf|"` - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - RANLIB=$ac_ct_RANLIB -else - RANLIB="$ac_cv_prog_RANLIB" -fi - - # Extract the first word of "rm", so it can be a program name with args. -set dummy rm; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_RM+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $RM in - [\\/]* | ?:[\\/]*) - ac_cv_path_RM="$RM" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" - ;; -esac -fi -RM=$ac_cv_path_RM - -if test -n "$RM"; then - echo "$as_me:$LINENO: result: $RM" >&5 -echo "${ECHO_T}$RM" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "mv", so it can be a program name with args. -set dummy mv; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_MV+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MV in - [\\/]* | ?:[\\/]*) - ac_cv_path_MV="$MV" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_MV" && ac_cv_path_MV="mv" - ;; -esac -fi -MV=$ac_cv_path_MV - -if test -n "$MV"; then - echo "$as_me:$LINENO: result: $MV" >&5 -echo "${ECHO_T}$MV" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "cp", so it can be a program name with args. -set dummy cp; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_CP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $CP in - [\\/]* | ?:[\\/]*) - ac_cv_path_CP="$CP" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_CP" && ac_cv_path_CP="cp" - ;; -esac -fi -CP=$ac_cv_path_CP - -if test -n "$CP"; then - echo "$as_me:$LINENO: result: $CP" >&5 -echo "${ECHO_T}$CP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "mkdir", so it can be a program name with args. -set dummy mkdir; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_MKDIR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MKDIR in - [\\/]* | ?:[\\/]*) - ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="mkdir" - ;; -esac -fi -MKDIR=$ac_cv_path_MKDIR - -if test -n "$MKDIR"; then - echo "$as_me:$LINENO: result: $MKDIR" >&5 -echo "${ECHO_T}$MKDIR" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "perl", so it can be a program name with args. -set dummy perl; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_PERL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $PERL in - [\\/]* | ?:[\\/]*) - ac_cv_path_PERL="$PERL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="perl" - ;; -esac -fi -PERL=$ac_cv_path_PERL - -if test -n "$PERL"; then - echo "$as_me:$LINENO: result: $PERL" >&5 -echo "${ECHO_T}$PERL" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "find", so it can be a program name with args. -set dummy find; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_FIND+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $FIND in - [\\/]* | ?:[\\/]*) - ac_cv_path_FIND="$FIND" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_FIND="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_FIND" && ac_cv_path_FIND="find" - ;; -esac -fi -FIND=$ac_cv_path_FIND - -if test -n "$FIND"; then - echo "$as_me:$LINENO: result: $FIND" >&5 -echo "${ECHO_T}$FIND" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "xargs", so it can be a program name with args. -set dummy xargs; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_XARGS+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $XARGS in - [\\/]* | ?:[\\/]*) - ac_cv_path_XARGS="$XARGS" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_XARGS="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_XARGS" && ac_cv_path_XARGS="xargs" - ;; -esac -fi -XARGS=$ac_cv_path_XARGS - -if test -n "$XARGS"; then - echo "$as_me:$LINENO: result: $XARGS" >&5 -echo "${ECHO_T}$XARGS" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - # Extract the first word of "ldconfig", so it can be a program name with args. -set dummy ldconfig; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_LDCONFIG+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $LDCONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_LDCONFIG="$LDCONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_dummy="$PATH:/sbin:/usr/local/sbin" -for as_dir in $as_dummy -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LDCONFIG="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_LDCONFIG" && ac_cv_path_LDCONFIG="ldconfig" - ;; -esac -fi -LDCONFIG=$ac_cv_path_LDCONFIG - -if test -n "$LDCONFIG"; then - echo "$as_me:$LINENO: result: $LDCONFIG" >&5 -echo "${ECHO_T}$LDCONFIG" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi - -if test "x$enable_gdb" = "xno"; then - DIRTY_CFLAGS="$CFLAGS" - CFLAGS="-O3" - for f in $DIRTY_CFLAGS; do - if test "x$f" != "x-O2" -a "x$f" != "x-O3" -a "x$f" != "x-O"; then - CFLAGS="$CFLAGS $f" - fi - done -fi - - -MMX_CFLAGS="-mmmx" -have_mmx_intrinsics=no - -if test "x$enable_mmx_optimization" = "xyes"; then - echo "$as_me:$LINENO: checking for MMX support" >&5 -echo $ECHO_N "checking for MMX support... $ECHO_C" >&6 - - save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $MMX_CFLAGS" - -cat >conftest.$ac_ext <<_ACEOF - -#if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)) -#error "Need GCC >= 3.4 for MMX intrinsics" -#endif -#include -int main () { - __m64 v = _mm_cvtsi32_si64 (1); - __m64 w = _mm_slli_si64 (v, 1); - v = _mm_add_pi32 (v, w); /* paddd */ - v = _mm_srl_pi32 (v, w); /* psrld */ - return _mm_cvtsi64_si32 (v); -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - have_mmx_intrinsics=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - - echo "$as_me:$LINENO: result: $have_mmx_intrinsics" >&5 -echo "${ECHO_T}$have_mmx_intrinsics" >&6 - CFLAGS=$save_CFLAGS -fi - -if test $have_mmx_intrinsics = yes ; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_MMX 1 -_ACEOF - -else - MMX_CFLAGS= -fi - - -afterimage_x_support=yes -if test "x$PATH_XTRA_CHECKED" != "xyes"; then - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6 -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -if test "x$ac_path_x_has_been_run" != xyes; then - echo "$as_me:$LINENO: checking for X" >&5 -echo $ECHO_N "checking for X... $ECHO_C" >&6 - -ac_path_x_has_been_run=yes - -# Check whether --with-x or --without-x was given. -if test "${with_x+set}" = set; then - withval="$with_x" - -fi; -# $have_x is `yes', `no', `disabled', or empty when we do not yet know. -if test "x$with_x" = xno; then - # The user explicitly disabled X. - have_x=disabled -else - if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then - # Both variables are already set. - have_x=yes - else - if test "${ac_cv_have_x+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # One or both of the vars are not set, and there is no cached value. -ac_x_includes=no ac_x_libraries=no -rm -fr conftest.dir -if mkdir conftest.dir; then - cd conftest.dir - # Make sure to not put "make" in the Imakefile rules, since we grep it out. - cat >Imakefile <<'_ACEOF' -acfindx: - @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' -_ACEOF - if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then - # GNU make sometimes prints "make[1]: Entering...", which would confuse us. - eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` - # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. - for ac_extension in a so sl dylib; do - if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && - test -f $ac_im_libdir/libX11.$ac_extension; then - ac_im_usrlibdir=$ac_im_libdir; break - fi - done - # Screen out bogus values from the imake configuration. They are - # bogus both because they are the default anyway, and because - # using them would break gcc on systems where it needs fixed includes. - case $ac_im_incroot in - /usr/include) ;; - *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; - esac - case $ac_im_usrlibdir in - /usr/lib | /lib) ;; - *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; - esac - fi - cd .. - rm -fr conftest.dir -fi - -# Standard set of common directories for X headers. -# Check X11 before X11Rn because it is often a symlink to the current release. -ac_x_header_dirs=' -/usr/X11/include -/usr/X11R6/include -/usr/X11R5/include -/usr/X11R4/include - -/usr/include/X11 -/usr/include/X11R6 -/usr/include/X11R5 -/usr/include/X11R4 - -/usr/local/X11/include -/usr/local/X11R6/include -/usr/local/X11R5/include -/usr/local/X11R4/include - -/usr/local/include/X11 -/usr/local/include/X11R6 -/usr/local/include/X11R5 -/usr/local/include/X11R4 - -/usr/X386/include -/usr/x386/include -/usr/XFree86/include/X11 - -/usr/include -/usr/local/include -/usr/unsupported/include -/usr/athena/include -/usr/local/x11r5/include -/usr/lpp/Xamples/include - -/usr/openwin/include -/usr/openwin/share/include' - -if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for a specified header file. - # First, try using that file with no special directory specified. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # We can compile using X headers with no special include directory. -ac_x_includes= -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Xlib.h"; then - ac_x_includes=$ac_dir - break - fi -done -fi -rm -f conftest.err conftest.$ac_ext -fi # $ac_x_includes = no - -if test "$ac_x_libraries" = no; then - # Check for the libraries. - # See if we find them without any special options. - # Don't add to $LIBS permanently. - ac_save_LIBS=$LIBS - LIBS="-lX11 $LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -int -main () -{ -XrmInitialize () - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - LIBS=$ac_save_LIBS -# We can link X programs with no special library path. -ac_x_libraries= -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -LIBS=$ac_save_LIBS -for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` -do - # Don't even attempt the hair of trying to link an X program! - for ac_extension in a so sl dylib; do - if test -r $ac_dir/libX11.$ac_extension; then - ac_x_libraries=$ac_dir - break 2 - fi - done -done -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi # $ac_x_libraries = no - -if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then - # Didn't find X anywhere. Cache the known absence of X. - ac_cv_have_x="have_x=no" -else - # Record where we found X for the cache. - ac_cv_have_x="have_x=yes \ - ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" -fi -fi - - fi - eval "$ac_cv_have_x" -fi # $with_x != no - -if test "$have_x" != yes; then - echo "$as_me:$LINENO: result: $have_x" >&5 -echo "${ECHO_T}$have_x" >&6 - no_x=yes -else - # If each of the values was on the command line, it overrides each guess. - test "x$x_includes" = xNONE && x_includes=$ac_x_includes - test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries - # Update the cache value to reflect the command line values. - ac_cv_have_x="have_x=yes \ - ac_x_includes=$x_includes ac_x_libraries=$x_libraries" - # It might be that x_includes is empty (headers are found in the - # standard search path. Then output the corresponding message - ac_out_x_includes=$x_includes - test "x$x_includes" = x && ac_out_x_includes="in standard search path" - echo "$as_me:$LINENO: result: libraries $x_libraries, headers $ac_out_x_includes" >&5 -echo "${ECHO_T}libraries $x_libraries, headers $ac_out_x_includes" >&6 -fi - -fi -if test "$no_x" = yes; then - # Not all programs may use this symbol, but it does not hurt to define it. - -cat >>confdefs.h <<\_ACEOF -#define X_DISPLAY_MISSING 1 -_ACEOF - - X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= -else - if test -n "$x_includes"; then - X_CFLAGS="$X_CFLAGS -I$x_includes" - fi - - # It would also be nice to do this for all -L options, not just this one. - if test -n "$x_libraries"; then - X_LIBS="$X_LIBS -L$x_libraries" - # For Solaris; some versions of Sun CC require a space after -R and - # others require no space. Words are not sufficient . . . . - case `(uname -sr) 2>/dev/null` in - "SunOS 5"*) - echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 -echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6 - ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_R_nospace=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_R_nospace=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test $ac_R_nospace = yes; then - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - X_LIBS="$X_LIBS -R$x_libraries" - else - LIBS="$ac_xsave_LIBS -R $x_libraries" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_R_space=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_R_space=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test $ac_R_space = yes; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - X_LIBS="$X_LIBS -R $x_libraries" - else - echo "$as_me:$LINENO: result: neither works" >&5 -echo "${ECHO_T}neither works" >&6 - fi - fi - LIBS=$ac_xsave_LIBS - esac - fi - - # Check for system-dependent libraries X programs must link with. - # Do this before checking for the system-independent R6 libraries - # (-lICE), since we may need -lsocket or whatever for X linking. - - if test "$ISC" = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" - else - # Martyn Johnson says this is needed for Ultrix, if the X - # libraries were built with DECnet support. And Karl Berry says - # the Alpha needs dnet_stub (dnet does not exist). - ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char XOpenDisplay (); -int -main () -{ -XOpenDisplay (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 -echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6 -if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldnet $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dnet_ntoa (); -int -main () -{ -dnet_ntoa (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dnet_dnet_ntoa=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dnet_dnet_ntoa=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 -echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6 -if test $ac_cv_lib_dnet_dnet_ntoa = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" -fi - - if test $ac_cv_lib_dnet_dnet_ntoa = no; then - echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 -echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6 -if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldnet_stub $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dnet_ntoa (); -int -main () -{ -dnet_ntoa (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dnet_stub_dnet_ntoa=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dnet_stub_dnet_ntoa=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 -echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6 -if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" -fi - - fi -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS="$ac_xsave_LIBS" - - # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, - # to get the SysV transport functions. - # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) - # needs -lnsl. - # The nsl library prevents programs from opening the X display - # on Irix 5.2, according to T.E. Dickey. - # The functions gethostbyname, getservbyname, and inet_addr are - # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. - echo "$as_me:$LINENO: checking for gethostbyname" >&5 -echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 -if test "${ac_cv_func_gethostbyname+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. - For example, HP-UX 11i declares gettimeofday. */ -#define gethostbyname innocuous_gethostbyname - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char gethostbyname (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef gethostbyname - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char gethostbyname (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) -choke me -#else -char (*f) () = gethostbyname; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != gethostbyname; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_gethostbyname=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_gethostbyname=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 -echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 - - if test $ac_cv_func_gethostbyname = no; then - echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 -echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 -if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lnsl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char gethostbyname (); -int -main () -{ -gethostbyname (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_nsl_gethostbyname=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_nsl_gethostbyname=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 -echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 -if test $ac_cv_lib_nsl_gethostbyname = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" -fi - - if test $ac_cv_lib_nsl_gethostbyname = no; then - echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 -echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 -if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lbsd $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char gethostbyname (); -int -main () -{ -gethostbyname (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_bsd_gethostbyname=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_bsd_gethostbyname=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 -echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 -if test $ac_cv_lib_bsd_gethostbyname = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" -fi - - fi - fi - - # lieder@skyler.mavd.honeywell.com says without -lsocket, - # socket/setsockopt and other routines are undefined under SCO ODT - # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary - # on later versions), says Simon Leinen: it contains gethostby* - # variants that don't use the name server (or something). -lsocket - # must be given before -lnsl if both are needed. We assume that - # if connect needs -lnsl, so does gethostbyname. - echo "$as_me:$LINENO: checking for connect" >&5 -echo $ECHO_N "checking for connect... $ECHO_C" >&6 -if test "${ac_cv_func_connect+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define connect to an innocuous variant, in case declares connect. - For example, HP-UX 11i declares gettimeofday. */ -#define connect innocuous_connect - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char connect (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef connect - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char connect (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_connect) || defined (__stub___connect) -choke me -#else -char (*f) () = connect; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != connect; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_connect=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_connect=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 -echo "${ECHO_T}$ac_cv_func_connect" >&6 - - if test $ac_cv_func_connect = no; then - echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 -echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 -if test "${ac_cv_lib_socket_connect+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsocket $X_EXTRA_LIBS $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char connect (); -int -main () -{ -connect (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_socket_connect=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_socket_connect=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 -echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 -if test $ac_cv_lib_socket_connect = yes; then - X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" -fi - - fi - - # Guillermo Gomez says -lposix is necessary on A/UX. - echo "$as_me:$LINENO: checking for remove" >&5 -echo $ECHO_N "checking for remove... $ECHO_C" >&6 -if test "${ac_cv_func_remove+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define remove to an innocuous variant, in case declares remove. - For example, HP-UX 11i declares gettimeofday. */ -#define remove innocuous_remove - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char remove (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef remove - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char remove (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_remove) || defined (__stub___remove) -choke me -#else -char (*f) () = remove; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != remove; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_remove=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_remove=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 -echo "${ECHO_T}$ac_cv_func_remove" >&6 - - if test $ac_cv_func_remove = no; then - echo "$as_me:$LINENO: checking for remove in -lposix" >&5 -echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6 -if test "${ac_cv_lib_posix_remove+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lposix $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char remove (); -int -main () -{ -remove (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_posix_remove=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_posix_remove=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 -echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6 -if test $ac_cv_lib_posix_remove = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" -fi - - fi - - # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. - echo "$as_me:$LINENO: checking for shmat" >&5 -echo $ECHO_N "checking for shmat... $ECHO_C" >&6 -if test "${ac_cv_func_shmat+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shmat to an innocuous variant, in case declares shmat. - For example, HP-UX 11i declares gettimeofday. */ -#define shmat innocuous_shmat - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shmat (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shmat - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shmat (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shmat) || defined (__stub___shmat) -choke me -#else -char (*f) () = shmat; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shmat; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shmat=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shmat=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 -echo "${ECHO_T}$ac_cv_func_shmat" >&6 - - if test $ac_cv_func_shmat = no; then - echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 -echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6 -if test "${ac_cv_lib_ipc_shmat+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lipc $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shmat (); -int -main () -{ -shmat (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_ipc_shmat=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_ipc_shmat=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 -echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6 -if test $ac_cv_lib_ipc_shmat = yes; then - X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" -fi - - fi - fi - - # Check for libraries that X11R6 Xt/Xaw programs need. - ac_save_LDFLAGS=$LDFLAGS - test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" - # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to - # check for ICE first), but we must link in the order -lSM -lICE or - # we get undefined symbols. So assume we have SM if we have ICE. - # These have to be linked with before -lX11, unlike the other - # libraries we check for below, so use a different variable. - # John Interrante, Karl Berry - echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 -echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6 -if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lICE $X_EXTRA_LIBS $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char IceConnectionNumber (); -int -main () -{ -IceConnectionNumber (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_ICE_IceConnectionNumber=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_ICE_IceConnectionNumber=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 -echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6 -if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then - X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" -fi - - LDFLAGS=$ac_save_LDFLAGS - -fi - -else - if test "x$have_x" != "xyes"; then - cat >>confdefs.h <<\_ACEOF -#define X_DISPLAY_MISSING 1 -_ACEOF - - afterimage_x_support=no - fi - -fi - -user_ldflags=$LDFLAGS - -if test "x$have_x" = "xyes"; then - x_libs="$X_LIBS $X_EXTRA_LIBS $X_PRE_LIBS" - if test "x$user_ldflags" = "x"; then - full_x_libs=$x_libs - else - full_x_libs="$user_ldflags $x_libs" - fi - echo "$as_me:$LINENO: checking for XOpenDisplay in -lX11" >&5 -echo $ECHO_N "checking for XOpenDisplay in -lX11... $ECHO_C" >&6 -if test "${ac_cv_lib_X11_XOpenDisplay+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lX11 $full_x_libs $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char XOpenDisplay (); -int -main () -{ -XOpenDisplay (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_X11_XOpenDisplay=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_X11_XOpenDisplay=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_X11_XOpenDisplay" >&5 -echo "${ECHO_T}$ac_cv_lib_X11_XOpenDisplay" >&6 -if test $ac_cv_lib_X11_XOpenDisplay = yes; then - x_libs="-lX11 $x_libs" -fi - -fi - - - -echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 -echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 -if test "${ac_cv_c_bigendian+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # See if sys/param.h defines the BYTE_ORDER macro. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include - -int -main () -{ -#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN - bogus endian macros -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - # It does; now see whether it defined to BIG_ENDIAN or not. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include - -int -main () -{ -#if BYTE_ORDER != BIG_ENDIAN - not big endian -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_bigendian=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_bigendian=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -# It does not; compile a test program. -if test "$cross_compiling" = yes; then - # try to guess the endianness by grepping values into an object file - ac_cv_c_bigendian=unknown - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; -short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; -void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } -short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; -short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; -void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } -int -main () -{ - _ascii (); _ebcdic (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then - ac_cv_c_bigendian=yes -fi -if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -int -main () -{ - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long l; - char c[sizeof (long)]; - } u; - u.l = 1; - exit (u.c[sizeof (long) - 1] == 1); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_bigendian=no -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_c_bigendian=yes -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 -echo "${ECHO_T}$ac_cv_c_bigendian" >&6 -case $ac_cv_c_bigendian in - yes) - -cat >>confdefs.h <<\_ACEOF -#define WORDS_BIGENDIAN 1 -_ACEOF - ;; - no) - ;; - *) - { { echo "$as_me:$LINENO: error: unknown endianness -presetting ac_cv_c_bigendian=no (or yes) will help" >&5 -echo "$as_me: error: unknown endianness -presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} - { (exit 1); exit 1; }; } ;; -esac - -echo "$as_me:$LINENO: checking for inline" >&5 -echo $ECHO_N "checking for inline... $ECHO_C" >&6 -if test "${ac_cv_c_inline+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_c_inline=no -for ac_kw in inline __inline__ __inline; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifndef __cplusplus -typedef int foo_t; -static $ac_kw foo_t static_foo () {return 0; } -$ac_kw foo_t foo () {return 0; } -#endif - -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_inline=$ac_kw; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 -echo "${ECHO_T}$ac_cv_c_inline" >&6 - - -case $ac_cv_c_inline in - inline | yes) ;; - *) - case $ac_cv_c_inline in - no) ac_val=;; - *) ac_val=$ac_cv_c_inline;; - esac - cat >>confdefs.h <<_ACEOF -#ifndef __cplusplus -#define inline $ac_val -#endif -_ACEOF - ;; -esac - -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep - - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -echo "$as_me:$LINENO: checking for long long" >&5 -echo $ECHO_N "checking for long long... $ECHO_C" >&6 -if test "${ac_cv_type_long_long+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((long long *) 0) - return 0; -if (sizeof (long long)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_long_long=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_long_long=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 -echo "${ECHO_T}$ac_cv_type_long_long" >&6 -if test $ac_cv_type_long_long = yes; then - -cat >>confdefs.h <<_ACEOF -#define HAVE_LONG_LONG 1 -_ACEOF - - -fi - - -echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 -echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6 -if test "${ac_cv_header_time+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include - -int -main () -{ -if ((struct tm *) 0) -return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_time=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_time=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 -echo "${ECHO_T}$ac_cv_header_time" >&6 -if test $ac_cv_header_time = yes; then - -cat >>confdefs.h <<\_ACEOF -#define TIME_WITH_SYS_TIME 1 -_ACEOF - -fi - - - - - - - - - -for ac_header in sys/wait.h sys/time.h malloc.h stdlib.h unistd.h stddef.h stdarg.h errno.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -have_shmimage=no -have_xext_lib=no -if test "x$enable_shmimage" = "xyes"; then - echo "$as_me:$LINENO: checking for XShmCreateImage in -lXext" >&5 -echo $ECHO_N "checking for XShmCreateImage in -lXext... $ECHO_C" >&6 -if test "${ac_cv_lib_Xext_XShmCreateImage+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lXext $full_x_libs $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char XShmCreateImage (); -int -main () -{ -XShmCreateImage (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_Xext_XShmCreateImage=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_Xext_XShmCreateImage=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XShmCreateImage" >&5 -echo "${ECHO_T}$ac_cv_lib_Xext_XShmCreateImage" >&6 -if test $ac_cv_lib_Xext_XShmCreateImage = yes; then - have_shmimage=yes -fi - - if test "x$have_shmimage" = "xyes"; then - if test "${ac_cv_header_sys_ipc_h+set}" = set; then - echo "$as_me:$LINENO: checking for sys/ipc.h" >&5 -echo $ECHO_N "checking for sys/ipc.h... $ECHO_C" >&6 -if test "${ac_cv_header_sys_ipc_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_ipc_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_ipc_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking sys/ipc.h usability" >&5 -echo $ECHO_N "checking sys/ipc.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking sys/ipc.h presence" >&5 -echo $ECHO_N "checking sys/ipc.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: sys/ipc.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: sys/ipc.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: sys/ipc.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: sys/ipc.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: sys/ipc.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: sys/ipc.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: sys/ipc.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/ipc.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: sys/ipc.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for sys/ipc.h" >&5 -echo $ECHO_N "checking for sys/ipc.h... $ECHO_C" >&6 -if test "${ac_cv_header_sys_ipc_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_sys_ipc_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_ipc_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_ipc_h" >&6 - -fi -if test $ac_cv_header_sys_ipc_h = yes; then - : -else - have_shmimage=no -fi - - - fi - if test "x$have_shmimage" = "xyes"; then - if test "${ac_cv_header_sys_shm_h+set}" = set; then - echo "$as_me:$LINENO: checking for sys/shm.h" >&5 -echo $ECHO_N "checking for sys/shm.h... $ECHO_C" >&6 -if test "${ac_cv_header_sys_shm_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_shm_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_shm_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking sys/shm.h usability" >&5 -echo $ECHO_N "checking sys/shm.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking sys/shm.h presence" >&5 -echo $ECHO_N "checking sys/shm.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: sys/shm.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: sys/shm.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/shm.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: sys/shm.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: sys/shm.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: sys/shm.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/shm.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: sys/shm.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/shm.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: sys/shm.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/shm.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: sys/shm.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/shm.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: sys/shm.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: sys/shm.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: sys/shm.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for sys/shm.h" >&5 -echo $ECHO_N "checking for sys/shm.h... $ECHO_C" >&6 -if test "${ac_cv_header_sys_shm_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_sys_shm_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_shm_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_shm_h" >&6 - -fi -if test $ac_cv_header_sys_shm_h = yes; then - : -else - have_shmimage=no -fi - - - fi - if test "x$have_shmimage" = "xyes"; then - have_xext_lib=yes - -cat >>confdefs.h <<\_ACEOF -#define XSHMIMAGE 1 -_ACEOF - - fi -fi - -HAVESHAPE="NOSHAPE" -if test "x$enable_shaping" = "xyes"; then - echo "$as_me:$LINENO: checking for XShapeCombineMask in -lXext" >&5 -echo $ECHO_N "checking for XShapeCombineMask in -lXext... $ECHO_C" >&6 -if test "${ac_cv_lib_Xext_XShapeCombineMask+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lXext $full_x_libs $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char XShapeCombineMask (); -int -main () -{ -XShapeCombineMask (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_Xext_XShapeCombineMask=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_Xext_XShapeCombineMask=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XShapeCombineMask" >&5 -echo "${ECHO_T}$ac_cv_lib_Xext_XShapeCombineMask" >&6 -if test $ac_cv_lib_Xext_XShapeCombineMask = yes; then - have_xext_lib=yes; -cat >>confdefs.h <<\_ACEOF -#define SHAPE 1 -_ACEOF - -fi - -fi - -if test "x$enable_glx" = "xyes"; then - echo "$as_me:$LINENO: checking for glDrawPixels in -lGL" >&5 -echo $ECHO_N "checking for glDrawPixels in -lGL... $ECHO_C" >&6 -if test "${ac_cv_lib_GL_glDrawPixels+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lGL $full_x_libs $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char glDrawPixels (); -int -main () -{ -glDrawPixels (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_GL_glDrawPixels=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_GL_glDrawPixels=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_GL_glDrawPixels" >&5 -echo "${ECHO_T}$ac_cv_lib_GL_glDrawPixels" >&6 -if test $ac_cv_lib_GL_glDrawPixels = yes; then - x_libs="$x_libs -lGL"; -cat >>confdefs.h <<\_ACEOF -#define HAVE_GLX 1 -_ACEOF - -fi - -fi - - -if test "x$have_xext_lib" = "xyes"; then - x_libs="$x_libs -lXext" -fi - - -image_format="xpm" - -AFTERIMAGE_LIBS=$x_libs - -if test "$with_xpm" = no; then - have_xpm=disabled -else - if test "$with_builtin_xpm" = no; then - SAVED_CFLAGS=$CPPFLAGS - if test "x$xpm_includes" != "xno"; then - XPM_CFLAGS="-I$xpm_includes" - CPPFLAGS="$CPPFLAGS $XPM_CFLAGS" - fi - have_libxpm=no - if test "${ac_cv_header_xpm_h+set}" = set; then - echo "$as_me:$LINENO: checking for xpm.h" >&5 -echo $ECHO_N "checking for xpm.h... $ECHO_C" >&6 -if test "${ac_cv_header_xpm_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_xpm_h" >&5 -echo "${ECHO_T}$ac_cv_header_xpm_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking xpm.h usability" >&5 -echo $ECHO_N "checking xpm.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking xpm.h presence" >&5 -echo $ECHO_N "checking xpm.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: xpm.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: xpm.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: xpm.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: xpm.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: xpm.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: xpm.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: xpm.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: xpm.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: xpm.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: xpm.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: xpm.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: xpm.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: xpm.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: xpm.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: xpm.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: xpm.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for xpm.h" >&5 -echo $ECHO_N "checking for xpm.h... $ECHO_C" >&6 -if test "${ac_cv_header_xpm_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_xpm_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_xpm_h" >&5 -echo "${ECHO_T}$ac_cv_header_xpm_h" >&6 - -fi -if test $ac_cv_header_xpm_h = yes; then - have_libxpm=yes -fi - - - if test "x$have_libxpm" = "xno"; then - if test "${ac_cv_header_X11_xpm_h+set}" = set; then - echo "$as_me:$LINENO: checking for X11/xpm.h" >&5 -echo $ECHO_N "checking for X11/xpm.h... $ECHO_C" >&6 -if test "${ac_cv_header_X11_xpm_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_X11_xpm_h" >&5 -echo "${ECHO_T}$ac_cv_header_X11_xpm_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking X11/xpm.h usability" >&5 -echo $ECHO_N "checking X11/xpm.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking X11/xpm.h presence" >&5 -echo $ECHO_N "checking X11/xpm.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: X11/xpm.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: X11/xpm.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: X11/xpm.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: X11/xpm.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: X11/xpm.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: X11/xpm.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: X11/xpm.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: X11/xpm.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: X11/xpm.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for X11/xpm.h" >&5 -echo $ECHO_N "checking for X11/xpm.h... $ECHO_C" >&6 -if test "${ac_cv_header_X11_xpm_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_X11_xpm_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_X11_xpm_h" >&5 -echo "${ECHO_T}$ac_cv_header_X11_xpm_h" >&6 - -fi -if test $ac_cv_header_X11_xpm_h = yes; then - have_libxpm_x11="yes" -fi - - - if test "x$have_libxpm_x11" = "xyes"; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_LIBXPM_X11 1 -_ACEOF - - have_libxpm=yes - fi - fi - if test "x$have_libxpm" = "xyes"; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_XPM 1 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_LIBXPM 1 -_ACEOF - - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lXpm" - fi - CPPFLAGS=$SAVED_CFLAGS - else - -cat >>confdefs.h <<\_ACEOF -#define HAVE_XPM 1 -_ACEOF - - XPM_CFLAGS= - fi -fi - - -JPEG_OBJS= -ZLIB_OBJS= -PNG_OBJS= - -have_jpeg= - -if test "$with_jpeg" = no; then - have_jpeg=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "x$jpeg_includes" != "xno"; then - JPEG_CFLAGS="-I$jpeg_includes" - CPPFLAGS="$CPPFLAGS $JPEG_CFLAGS" - fi - if test "with_builtin_jpeg" = yes -a ! -f libjpeg/jpeglib.h; then - with_builtin_jpeg=no - fi - if test "$with_builtin_jpeg" = no; then - if test "${ac_cv_header_jpeglib_h+set}" = set; then - echo "$as_me:$LINENO: checking for jpeglib.h" >&5 -echo $ECHO_N "checking for jpeglib.h... $ECHO_C" >&6 -if test "${ac_cv_header_jpeglib_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_jpeglib_h" >&5 -echo "${ECHO_T}$ac_cv_header_jpeglib_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking jpeglib.h usability" >&5 -echo $ECHO_N "checking jpeglib.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking jpeglib.h presence" >&5 -echo $ECHO_N "checking jpeglib.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: jpeglib.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: jpeglib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: jpeglib.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: jpeglib.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: jpeglib.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: jpeglib.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: jpeglib.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: jpeglib.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: jpeglib.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: jpeglib.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: jpeglib.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: jpeglib.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: jpeglib.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: jpeglib.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: jpeglib.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: jpeglib.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for jpeglib.h" >&5 -echo $ECHO_N "checking for jpeglib.h... $ECHO_C" >&6 -if test "${ac_cv_header_jpeglib_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_jpeglib_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_jpeglib_h" >&5 -echo "${ECHO_T}$ac_cv_header_jpeglib_h" >&6 - -fi -if test $ac_cv_header_jpeglib_h = yes; then - have_jpeg=yes -fi - - - fi - if test "$have_jpeg" = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_JPEG 1 -_ACEOF - - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -ljpeg" - else - echo "$as_me:$LINENO: checking built-in JPEG library" >&5 -echo $ECHO_N "checking built-in JPEG library... $ECHO_C" >&6 - if test -f libjpeg/jpeglib.h; then - JPEG_OBJS='$(LIBJPEG_OBJS)' - -cat >>confdefs.h <<\_ACEOF -#define HAVE_JPEG 1 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_BUILTIN_JPEG 1 -_ACEOF - - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - fi - fi - CPPFLAGS=$SAVED_CFLAGS -fi - - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_PROTOTYPES 1 -_ACEOF - -echo "$as_me:$LINENO: checking for unsigned char" >&5 -echo $ECHO_N "checking for unsigned char... $ECHO_C" >&6 -if test "${ac_cv_type_unsigned_char+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((unsigned char *) 0) - return 0; -if (sizeof (unsigned char)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_unsigned_char=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_unsigned_char=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_char" >&5 -echo "${ECHO_T}$ac_cv_type_unsigned_char" >&6 - -echo "$as_me:$LINENO: checking for unsigned short" >&5 -echo $ECHO_N "checking for unsigned short... $ECHO_C" >&6 -if test "${ac_cv_type_unsigned_short+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((unsigned short *) 0) - return 0; -if (sizeof (unsigned short)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_unsigned_short=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_unsigned_short=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_short" >&5 -echo "${ECHO_T}$ac_cv_type_unsigned_short" >&6 - -echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 -echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 -if test "${ac_cv_c_const+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -/* FIXME: Include the comments suggested by Paul. */ -#ifndef __cplusplus - /* Ultrix mips cc rejects this. */ - typedef int charset[2]; - const charset x; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *ccp; - char **p; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - ccp = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++ccp; - p = (char**) ccp; - ccp = (char const *const *) p; - { /* SCO 3.2v4 cc rejects this. */ - char *t; - char const *s = 0 ? (char *) 0 : (char const *) 0; - - *t++ = 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - } -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_const=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_const=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 -echo "${ECHO_T}$ac_cv_c_const" >&6 -if test $ac_cv_c_const = no; then - -cat >>confdefs.h <<\_ACEOF -#define const -_ACEOF - -fi - - -echo "$as_me:$LINENO: checking whether char is unsigned" >&5 -echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6 -if test "${ac_cv_c_char_unsigned+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -static int test_array [1 - 2 * !(((char) -1) < 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_char_unsigned=no -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_char_unsigned=yes -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_c_char_unsigned" >&5 -echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6 -if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then - cat >>confdefs.h <<\_ACEOF -#define __CHAR_UNSIGNED__ 1 -_ACEOF - -fi - - -have_png=no -have_zlib=no - -if test "$with_png" = no; then - have_png=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "$png_includes" != no; then - PNG_CFLAGS="-I$png_includes" - CPPFLAGS="$CPPFLAGS $PNG_CFLAGS" - fi - if test "$with_builtin_png" = yes -a ! -f libpng/png.h; then - with_builtin_png=no - fi - if test "$with_builtin_zlib" = yes -a ! -f zlib/zlib.h; then - with_builtin_zlib=no - fi - - if test "$with_builtin_png" = no; then - if test "${ac_cv_header_png_h+set}" = set; then - echo "$as_me:$LINENO: checking for png.h" >&5 -echo $ECHO_N "checking for png.h... $ECHO_C" >&6 -if test "${ac_cv_header_png_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 -echo "${ECHO_T}$ac_cv_header_png_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking png.h usability" >&5 -echo $ECHO_N "checking png.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking png.h presence" >&5 -echo $ECHO_N "checking png.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: png.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: png.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: png.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: png.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: png.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: png.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for png.h" >&5 -echo $ECHO_N "checking for png.h... $ECHO_C" >&6 -if test "${ac_cv_header_png_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_png_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 -echo "${ECHO_T}$ac_cv_header_png_h" >&6 - -fi -if test $ac_cv_header_png_h = yes; then - have_png=yes with_builtin_zlib=no -fi - - - fi - if test "$with_builtin_zlib" = no; then - -for ac_header in zlib.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - have_zlib=yes -else - have_zlib=no -fi - -done - - fi - if test "$have_png" = yes; then - echo "$as_me:$LINENO: checking for png_get_sRGB in png.h" >&5 -echo $ECHO_N "checking for png_get_sRGB in png.h... $ECHO_C" >&6 - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "png_get_sRGB" >/dev/null 2>&1; then - : -else - have_png=no -fi -rm -f conftest* - - echo "$as_me:$LINENO: result: $have_png" >&5 -echo "${ECHO_T}$have_png" >&6 - fi - if test "$have_png" = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_PNG 1 -_ACEOF - - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lpng" - image_format="png" - else - echo "$as_me:$LINENO: checking built-in PNG library" >&5 -echo $ECHO_N "checking built-in PNG library... $ECHO_C" >&6 - if test -f libpng/png.h; then - PNG_OBJS='$(LIBPNG_OBJS)' - -cat >>confdefs.h <<\_ACEOF -#define HAVE_PNG 1 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_BUILTIN_PNG 1 -_ACEOF - - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - if test "$have_zlib" = no; then - echo "$as_me:$LINENO: checking built-in ZLIB library" >&5 -echo $ECHO_N "checking built-in ZLIB library... $ECHO_C" >&6 - if test -f zlib/zlib.h; then - ZLIB_OBJS='$(ZLIB_OBJS)' - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - fi - fi - image_format="png" - have_png=yes - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - fi - fi - CPPFLAGS=$SAVED_CFLAGS -fi - - -have_gif=no -if test "$with_gif$with_ungif" = nono; then - have_gif=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "$gif_includes" != no; then - GIF_CFLAGS="-I$gif_includes" - CPPFLAGS="$CPPFLAGS $GIF_CFLAGS" - fi - if test "${ac_cv_header_gif_lib_h+set}" = set; then - echo "$as_me:$LINENO: checking for gif_lib.h" >&5 -echo $ECHO_N "checking for gif_lib.h... $ECHO_C" >&6 -if test "${ac_cv_header_gif_lib_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_gif_lib_h" >&5 -echo "${ECHO_T}$ac_cv_header_gif_lib_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking gif_lib.h usability" >&5 -echo $ECHO_N "checking gif_lib.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking gif_lib.h presence" >&5 -echo $ECHO_N "checking gif_lib.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: gif_lib.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: gif_lib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: gif_lib.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: gif_lib.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: gif_lib.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: gif_lib.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: gif_lib.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: gif_lib.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: gif_lib.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: gif_lib.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: gif_lib.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: gif_lib.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: gif_lib.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: gif_lib.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: gif_lib.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: gif_lib.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for gif_lib.h" >&5 -echo $ECHO_N "checking for gif_lib.h... $ECHO_C" >&6 -if test "${ac_cv_header_gif_lib_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_gif_lib_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_gif_lib_h" >&5 -echo "${ECHO_T}$ac_cv_header_gif_lib_h" >&6 - -fi -if test $ac_cv_header_gif_lib_h = yes; then - have_gif=yes -fi - - - CPPFLAGS=$SAVED_CFLAGS - if test "x$have_gif" = "xyes"; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_GIF 1 -_ACEOF - - if test "$with_gif" = no; then - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lungif" - else - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lgif" - fi - fi -fi - -if test "x$have_gif" != "xyes"; then - if test "x$with_builtin_gif" = "xyes"; then - echo "$as_me:$LINENO: checking using built-in UNGIF library" >&5 -echo $ECHO_N "checking using built-in UNGIF library... $ECHO_C" >&6 - if test -f libungif/gif_lib.h; then - UNGIF_OBJS='$(LIBUNGIF_OBJS)' - -cat >>confdefs.h <<\_ACEOF -#define HAVE_GIF 1 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_BUILTIN_UNGIF 1 -_ACEOF - - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - have_gif=yes - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - fi - fi -fi - - - - -if test "$with_tiff" = no; then - have_tiff=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "$tiff_includes" != no; then - TIFF_CFLAGS="-I$tiff_includes" - CPPFLAGS="$CPPFLAGS $TIFF_CFLAGS" - fi - if test "${ac_cv_header_tiffio_h+set}" = set; then - echo "$as_me:$LINENO: checking for tiffio.h" >&5 -echo $ECHO_N "checking for tiffio.h... $ECHO_C" >&6 -if test "${ac_cv_header_tiffio_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_tiffio_h" >&5 -echo "${ECHO_T}$ac_cv_header_tiffio_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking tiffio.h usability" >&5 -echo $ECHO_N "checking tiffio.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking tiffio.h presence" >&5 -echo $ECHO_N "checking tiffio.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: tiffio.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: tiffio.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: tiffio.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: tiffio.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: tiffio.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: tiffio.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: tiffio.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: tiffio.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: tiffio.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: tiffio.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: tiffio.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: tiffio.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: tiffio.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: tiffio.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: tiffio.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: tiffio.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for tiffio.h" >&5 -echo $ECHO_N "checking for tiffio.h... $ECHO_C" >&6 -if test "${ac_cv_header_tiffio_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_tiffio_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_tiffio_h" >&5 -echo "${ECHO_T}$ac_cv_header_tiffio_h" >&6 - -fi -if test $ac_cv_header_tiffio_h = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_TIFF 1 -_ACEOF - AFTERIMAGE_LIBS="-ltiff $AFTERIMAGE_LIBS" have_tiff=yes -fi - - - CPPFLAGS=$SAVED_CFLAGS -fi - - -if test "$have_tiff" = yes -o "$have_png" = yes ; then - if test "x$ZLIB_OBJS" = "x" -a "$have_zlib" = yes; then - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lz" - fi -fi - -have_svg= -if test "$with_svg" = no; then - have_svg=disabled -else - if test -z "$PKG_CONFIG"; then - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_PKG_CONFIG+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG - -if test -n "$PKG_CONFIG"; then - echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 -echo "${ECHO_T}$PKG_CONFIG" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - fi - if test "$PKG_CONFIG" = "no" ; then - echo "$as_me:$LINENO: checking if librsvg 2.0 is available" >&5 -echo $ECHO_N "checking if librsvg 2.0 is available... $ECHO_C" >&6 - echo "$as_me:$LINENO: result: pkg-config is not found. Cannot check for librsvg 2.0." >&5 -echo "${ECHO_T}pkg-config is not found. Cannot check for librsvg 2.0." >&6 - have_svg=no - else - have_svg=yes - pkg_modules="librsvg-2.0 >= 2.0.0" - - - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_PKG_CONFIG+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG - -if test -n "$PKG_CONFIG"; then - echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 -echo "${ECHO_T}$PKG_CONFIG" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_path_PKG_CONFIG"; then - ac_pt_PKG_CONFIG=$PKG_CONFIG - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $ac_pt_PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - ;; -esac -fi -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG - -if test -n "$ac_pt_PKG_CONFIG"; then - echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 -echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - PKG_CONFIG=$ac_pt_PKG_CONFIG -else - PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -fi - -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=0.9.0 - echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 -echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - PKG_CONFIG="" - fi - -fi - -pkg_failed=no -echo "$as_me:$LINENO: checking for SVG" >&5 -echo $ECHO_N "checking for SVG... $ECHO_C" >&6 - -if test -n "$PKG_CONFIG"; then - if test -n "$SVG_CFLAGS"; then - pkg_cv_SVG_CFLAGS="$SVG_CFLAGS" - else - if test -n "$PKG_CONFIG" && \ - { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$pkg_modules\"") >&5 - ($PKG_CONFIG --exists --print-errors "$pkg_modules") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - pkg_cv_SVG_CFLAGS=`$PKG_CONFIG --cflags "$pkg_modules" 2>/dev/null` -else - pkg_failed=yes -fi - fi -else - pkg_failed=untried -fi -if test -n "$PKG_CONFIG"; then - if test -n "$SVG_LIBS"; then - pkg_cv_SVG_LIBS="$SVG_LIBS" - else - if test -n "$PKG_CONFIG" && \ - { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$pkg_modules\"") >&5 - ($PKG_CONFIG --exists --print-errors "$pkg_modules") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - pkg_cv_SVG_LIBS=`$PKG_CONFIG --libs "$pkg_modules" 2>/dev/null` -else - pkg_failed=yes -fi - fi -else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - SVG_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$pkg_modules"` - else - SVG_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$pkg_modules"` - fi - # Put the nasty error message in config.log where it belongs - echo "$SVG_PKG_ERRORS" >&5 - - have_svg=no -elif test $pkg_failed = untried; then - have_svg=no -else - SVG_CFLAGS=$pkg_cv_SVG_CFLAGS - SVG_LIBS=$pkg_cv_SVG_LIBS - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - : -fi - - if test "x$have_svg" = "xyes"; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_SVG 1 -_ACEOF - - AFTERIMAGE_LIBS="$SVG_LIBS $AFTERIMAGE_LIBS" - fi - fi -fi - - - -AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lm" - - -TTF_INCLUDES= - -if test "x$with_ttf" = "xno"; then - have_ttf=disabled -else - if test "x$ttf_includes" = "xno"; then - echo "$as_me:$LINENO: checking headers required by TTF support" >&5 -echo $ECHO_N "checking headers required by TTF support... $ECHO_C" >&6 - if freetype-config --cflags >/dev/null ;then - present_incs="$CCFLAGS $x_includes"; - for l in `freetype-config --cflags` ; do - inc_found=no - for p in `echo "$present_incs"` ; do - if test "x$l" = "x$p" ; then - inc_found=yes; - fi; - if test "x$l" = "x-I$p" ; then - inc_found=yes; - fi; - done; - if test "x$inc_found" != "xyes" ; then - TTF_INCLUDES="$TTF_INCLUDES $l" ; - fi; - done; - echo "$as_me:$LINENO: result: $TTF_INCLUDES" >&5 -echo "${ECHO_T}$TTF_INCLUDES" >&6 - saved_CPPFLAGS=$CPPFLAGS - saved_CFLAGS=$CFLAGS - CPPFLAGS="$TTF_INCLUDES $CPPFLAGS" - CFLAGS="$CFLAGS $TTF_INCLUDES $XPM_CFLAGS $JPEG_CFLAGS $PNG_CFLAGS $GIF_CFLAGS $TIFF_CFLAGS $SVG_CFLAGS $X_CFLAGS" - have_ft2build=no - -for ac_header in ft2build.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - have_ft2build=yes -fi - -done - - echo "$as_me:$LINENO: checking freetype/freetype.h " >&5 -echo $ECHO_N "checking freetype/freetype.h ... $ECHO_C" >&6 - have_ttf=no - have_freetype_freetype=no - have_freetype=no - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "FT_Face" >/dev/null 2>&1; then - have_freetype_freetype=yes -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6;echo "$as_me:$LINENO: checking freetype.h" >&5 -echo $ECHO_N "checking freetype.h... $ECHO_C" >&6; \ - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "FT_Face" >/dev/null 2>&1; then - have_freetype=yes -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -rm -f conftest* - - -fi -rm -f conftest* - - if test "x$have_ft2build" = "xno" ; then - if test "x$have_freetype_freetype" = "xyes" ; then - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - int main(){FT_Face f; return 0;} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - have_ttf=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - elif test "x$have_freetype" = "xyes" ; then - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - int main(){FT_Face f; return 0;} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - have_ttf=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - fi; - elif test "x$have_freetype_freetype" = "xyes" ; then - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - #include - int main(){FT_Face f; return 0;} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - have_ttf=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - elif test "x$have_freetype" = "xyes" ; then - if test "$cross_compiling" = yes; then - { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - #include - int main(){FT_Face f; return 0;} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - have_ttf=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - fi; - if test "x$have_ttf" = "xyes" ; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_FREETYPE 1 -_ACEOF - - if test "x$have_freetype_freetype" = "xyes" ; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_FREETYPE_FREETYPE 1 -_ACEOF - - fi; - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - fi; - CPPFLAGS=$saved_CPPFLAGS - CFLAGS=$saved_CFLAGS - else - enable_ttf=no ; - echo "$as_me:$LINENO: result: none found" >&5 -echo "${ECHO_T}none found" >&6 - echo "You have to install FreeType libary in order to be able to use TTF fonts." - have_ttf=no - fi; - else - TTF_INCLUDES=$ttf_includes - -cat >>confdefs.h <<\_ACEOF -#define HAVE_FREETYPE 1 -_ACEOF - - have_ttf=yes - fi - if test "$have_ttf" = yes; then - if test "x$ttf_includes" = "xno"; then - AFTERIMAGE_LIBS="`freetype-config --libs` $AFTERIMAGE_LIBS" - fi - fi -fi; - - - - - - - -AFTERIMAGE_LIBS_EXTERNAL=$AFTERIMAGE_LIBS - - -USE_DEFAULT_AFTERBASE=0 -AFTERBASE_INCS_PATH= -if test "x$with_afterbase" != "xno"; then - echo "$as_me:$LINENO: checking libAfterBase headers in ../libAfterBase" >&5 -echo $ECHO_N "checking libAfterBase headers in ../libAfterBase... $ECHO_C" >&6 - have_afterbase=yes - if test "x$afterbase_includes" = "xno"; then - if test -r "../libAfterBase/astypes.h"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - AFTERBASE_INCS_PATH="../" - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - if test "${ac_cv_header_libAfterBase_astypes_h+set}" = set; then - echo "$as_me:$LINENO: checking for libAfterBase/astypes.h" >&5 -echo $ECHO_N "checking for libAfterBase/astypes.h... $ECHO_C" >&6 -if test "${ac_cv_header_libAfterBase_astypes_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_libAfterBase_astypes_h" >&5 -echo "${ECHO_T}$ac_cv_header_libAfterBase_astypes_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking libAfterBase/astypes.h usability" >&5 -echo $ECHO_N "checking libAfterBase/astypes.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking libAfterBase/astypes.h presence" >&5 -echo $ECHO_N "checking libAfterBase/astypes.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: libAfterBase/astypes.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: libAfterBase/astypes.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for libAfterBase/astypes.h" >&5 -echo $ECHO_N "checking for libAfterBase/astypes.h... $ECHO_C" >&6 -if test "${ac_cv_header_libAfterBase_astypes_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_libAfterBase_astypes_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_libAfterBase_astypes_h" >&5 -echo "${ECHO_T}$ac_cv_header_libAfterBase_astypes_h" >&6 - -fi -if test $ac_cv_header_libAfterBase_astypes_h = yes; then - USE_DEFAULT_AFTERBASE=1 -else - have_afterbase=no -fi - - - fi - else - AFTERBASE_INCS_PATH="$afterbase_includes/" - echo "$as_me:$LINENO: result: $AFTERBASE_INCS_PATH" >&5 -echo "${ECHO_T}$AFTERBASE_INCS_PATH" >&6 - fi -else - echo "$as_me:$LINENO: checking libAfterBase" >&5 -echo $ECHO_N "checking libAfterBase... $ECHO_C" >&6 -fi - -AFTERBASE_C=afterbase.o -HAVE_AFTERBASE_FLAG=0 -if test "x$have_afterbase" = "xyes"; then - HAVE_AFTERBASE_FLAG=1 - AFTERBASE_C= - if test "x$CYGWIN" = "xno" -a "x$GCC" = "xyes" ; then - user_ldflags="$user_ldflags $RDYNAMIC" - fi - if test "x$have_x" != "xyes" -a "x$have_gif" = "xyes"; then - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lAfterBase" - else - AFTERIMAGE_LIBS="-lAfterBase $AFTERIMAGE_LIBS" - fi - if test -r "../libAfterBase/astypes.h"; then - AFTERIMAGE_APPS_LIBS="-L../ -L../../libAfterBase -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_TEST_LIBS="-L./ -L../libAfterBase -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_LIB_LIBS="-L./ -L../libAfterBase $AFTERIMAGE_LIBS" - else - AFTERIMAGE_APPS_LIBS="-L../ -L$libdir -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_TEST_LIBS="-L./ -L$libdir -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_LIB_LIBS="-L./ -L$libdir $AFTERIMAGE_LIBS" - fi - -cat >>confdefs.h <<\_ACEOF -#define HAVE_AFTERBASE 1 -_ACEOF - -else - AFTERIMAGE_APPS_LIBS="-L../ -lAfterImage $AFTERIMAGE_LIBS_EXTERNAL" - AFTERIMAGE_TEST_LIBS="-L./ -lAfterImage $AFTERIMAGE_LIBS_EXTERNAL" - AFTERIMAGE_LIB_LIBS="-L./ $AFTERIMAGE_LIBS_EXTERNAL" - if test "$with_afterbase" = "no"; then - echo "$as_me:$LINENO: result: disabled" >&5 -echo "${ECHO_T}disabled" >&6 - fi - - - - - -ac_header_dirent=no -for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do - as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 -echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include <$ac_hdr> - -int -main () -{ -if ((DIR *) 0) -return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 -_ACEOF - -ac_header_dirent=$ac_hdr; break -fi - -done -# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. -if test $ac_header_dirent = dirent.h; then - echo "$as_me:$LINENO: checking for library containing opendir" >&5 -echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 -if test "${ac_cv_search_opendir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -ac_cv_search_opendir=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir (); -int -main () -{ -opendir (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_opendir="none required" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_opendir" = no; then - for ac_lib in dir; do - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir (); -int -main () -{ -opendir (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_opendir="-l$ac_lib" -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done -fi -LIBS=$ac_func_search_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 -echo "${ECHO_T}$ac_cv_search_opendir" >&6 -if test "$ac_cv_search_opendir" != no; then - test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" - -fi - -else - echo "$as_me:$LINENO: checking for library containing opendir" >&5 -echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 -if test "${ac_cv_search_opendir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -ac_cv_search_opendir=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir (); -int -main () -{ -opendir (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_opendir="none required" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_opendir" = no; then - for ac_lib in x; do - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir (); -int -main () -{ -opendir (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_opendir="-l$ac_lib" -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done -fi -LIBS=$ac_func_search_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 -echo "${ECHO_T}$ac_cv_search_opendir" >&6 -if test "$ac_cv_search_opendir" != no; then - test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" - -fi - -fi - - -for ac_header in sys/dirent.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to as-bugs@afterstep.org ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -fi - - - - - - - - - - - -CLEAN_AFTERIMAGE_LIBS= -for L in $AFTERIMAGE_LIBS; do - if test "$L" != "-L$libdir"; then - CLEAN_AFTERIMAGE_LIBS="$CLEAN_AFTERIMAGE_LIBS $L" - fi -done -AFTERIMAGE_LIBS="-L$libdir -lAfterImage $CLEAN_AFTERIMAGE_LIBS" - - -if test "x$enable_staticlibs" = "xyes"; then - LIBPROG='$(LIB_STATIC)' - LIBINSTALL="install.static" - LIBUNINSTALL="install.static" -else - enable_sharedlibs="yes" -fi -if test "x$enable_sharedlibs" = "xyes"; then - if test "x$CYGWIN" = "xyes" ; then - tmp='$(LIB_SHARED_CYG)' - tmp2='install.cyg' - else - tmp='$(LIB_SHARED)' - tmp2='install.dyn' - fi - LIBPROG="$LIBPROG $tmp" - LIBINSTALL="$LIBINSTALL $tmp2" - LIBUNINSTALL="uninstall.static un$tmp2" -fi - -if test "x$enable_xlocale" = "xyes"; then - DEFINE_XLOCALE="-DX_LOCALE" -fi - - -if test "x$enable_i18n" = "xyes"; then -cat >>confdefs.h <<\_ACEOF -#define I18N 1 -_ACEOF - fi -if test "x$enable_audit" = "xyes"; then -cat >>confdefs.h <<\_ACEOF -#define DEBUG_ALLOCS 1 -_ACEOF - fi - - - - - - - - - - - - - - - - - - - -LIBAFTERIMAGEFILES=.shared - - -APPSDEPS= -if test -d apps ; then - APPSDEPS='$(APPS_DEPS)' - ac_config_files="$ac_config_files apps/Makefile" - -fi - -if test -d aftershow ; then - ac_config_files="$ac_config_files aftershow/Makefile" - -fi - - - - ac_config_files="$ac_config_files Makefile afterbase.h afterimage-libs afterimage-config" -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -{ - (set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} | - sed ' - t clear - : clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" - cat confcache >$cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - -DEFS=-DHAVE_CONFIG_H - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - -exec 6>&1 - -# Open the log real soon, to keep \$[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - -This file was extended by libAfterImage $as_me 1.20, which was -generated by GNU Autoconf 2.59. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 -_ACEOF - -# Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi - -cat >>$CONFIG_STATUS <<\_ACEOF - -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Report bugs to ." -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -libAfterImage config.status 1.20 -configured by $0, generated by GNU Autoconf 2.59, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2003 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -INSTALL="$INSTALL" -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` - ac_shift=: - ;; - -*) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; - esac - - case $ac_option in - # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" - ac_need_defaults=false;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF - - - - - -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_config_target in $ac_config_targets -do - case "$ac_config_target" in - # Handling of arguments. - "apps/Makefile" ) CONFIG_FILES="$CONFIG_FILES apps/Makefile" ;; - "aftershow/Makefile" ) CONFIG_FILES="$CONFIG_FILES aftershow/Makefile" ;; - "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "afterbase.h" ) CONFIG_FILES="$CONFIG_FILES afterbase.h" ;; - "afterimage-libs" ) CONFIG_FILES="$CONFIG_FILES afterimage-libs" ;; - "afterimage-config" ) CONFIG_FILES="$CONFIG_FILES afterimage-config" ;; - "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.h.in" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. -$debug || -{ - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF - -# -# CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s,@SHELL@,$SHELL,;t t -s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t -s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t -s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s,@exec_prefix@,$exec_prefix,;t t -s,@prefix@,$prefix,;t t -s,@program_transform_name@,$program_transform_name,;t t -s,@bindir@,$bindir,;t t -s,@sbindir@,$sbindir,;t t -s,@libexecdir@,$libexecdir,;t t -s,@datadir@,$datadir,;t t -s,@sysconfdir@,$sysconfdir,;t t -s,@sharedstatedir@,$sharedstatedir,;t t -s,@localstatedir@,$localstatedir,;t t -s,@libdir@,$libdir,;t t -s,@includedir@,$includedir,;t t -s,@oldincludedir@,$oldincludedir,;t t -s,@infodir@,$infodir,;t t -s,@mandir@,$mandir,;t t -s,@build_alias@,$build_alias,;t t -s,@host_alias@,$host_alias,;t t -s,@target_alias@,$target_alias,;t t -s,@DEFS@,$DEFS,;t t -s,@ECHO_C@,$ECHO_C,;t t -s,@ECHO_N@,$ECHO_N,;t t -s,@ECHO_T@,$ECHO_T,;t t -s,@LIBS@,$LIBS,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t -s,@LN_S@,$LN_S,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t -s,@target@,$target,;t t -s,@target_cpu@,$target_cpu,;t t -s,@target_vendor@,$target_vendor,;t t -s,@target_os@,$target_os,;t t -s,@INSTALL@,$INSTALL,;t t -s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t -s,@INSTALL_DATA@,$INSTALL_DATA,;t t -s,@INSTALL_LIB@,$INSTALL_LIB,;t t -s,@RANLIB@,$RANLIB,;t t -s,@RM@,$RM,;t t -s,@MV@,$MV,;t t -s,@CP@,$CP,;t t -s,@MKDIR@,$MKDIR,;t t -s,@PERL@,$PERL,;t t -s,@FIND@,$FIND,;t t -s,@XARGS@,$XARGS,;t t -s,@LDCONFIG@,$LDCONFIG,;t t -s,@LEX@,$LEX,;t t -s,@LEXLIB@,$LEXLIB,;t t -s,@YACC@,$YACC,;t t -s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t -s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t -s,@MMX_CFLAGS@,$MMX_CFLAGS,;t t -s,@CPP@,$CPP,;t t -s,@X_CFLAGS@,$X_CFLAGS,;t t -s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t -s,@X_LIBS@,$X_LIBS,;t t -s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t -s,@EGREP@,$EGREP,;t t -s,@XPM_CFLAGS@,$XPM_CFLAGS,;t t -s,@JPEG_CFLAGS@,$JPEG_CFLAGS,;t t -s,@PNG_CFLAGS@,$PNG_CFLAGS,;t t -s,@GIF_CFLAGS@,$GIF_CFLAGS,;t t -s,@TIFF_CFLAGS@,$TIFF_CFLAGS,;t t -s,@PKG_CONFIG@,$PKG_CONFIG,;t t -s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t -s,@SVG_CFLAGS@,$SVG_CFLAGS,;t t -s,@SVG_LIBS@,$SVG_LIBS,;t t -s,@TTF_INCLUDES@,$TTF_INCLUDES,;t t -s,@JPEG_OBJS@,$JPEG_OBJS,;t t -s,@ZLIB_OBJS@,$ZLIB_OBJS,;t t -s,@PNG_OBJS@,$PNG_OBJS,;t t -s,@UNGIF_OBJS@,$UNGIF_OBJS,;t t -s,@AFTERIMAGE_LIBS_EXTERNAL@,$AFTERIMAGE_LIBS_EXTERNAL,;t t -s,@AFTERBASE_INCS_PATH@,$AFTERBASE_INCS_PATH,;t t -s,@USE_DEFAULT_AFTERBASE@,$USE_DEFAULT_AFTERBASE,;t t -s,@HAVE_AFTERBASE_FLAG@,$HAVE_AFTERBASE_FLAG,;t t -s,@AFTERBASE_C@,$AFTERBASE_C,;t t -s,@have_afterbase@,$have_afterbase,;t t -s,@AFTERIMAGE_APPS_LIBS@,$AFTERIMAGE_APPS_LIBS,;t t -s,@AFTERIMAGE_TEST_LIBS@,$AFTERIMAGE_TEST_LIBS,;t t -s,@AFTERIMAGE_LIB_LIBS@,$AFTERIMAGE_LIB_LIBS,;t t -s,@afterimage_x_support@,$afterimage_x_support,;t t -s,@AFTERIMAGE_LIBS@,$AFTERIMAGE_LIBS,;t t -s,@image_format@,$image_format,;t t -s,@version@,$version,;t t -s,@version_major@,$version_major,;t t -s,@lib_name@,$lib_name,;t t -s,@lib_file_name@,$lib_file_name,;t t -s,@with_locale@,$with_locale,;t t -s,@user_ldflags@,$user_ldflags,;t t -s,@x_libs@,$x_libs,;t t -s,@LIBPROG@,$LIBPROG,;t t -s,@LIBINSTALL@,$LIBINSTALL,;t t -s,@DEFINE_XLOCALE@,$DEFINE_XLOCALE,;t t -s,@APPSDEPS@,$APPSDEPS,;t t -s,@LIBOBJS@,$LIBOBJS,;t t -s,@LTLIBOBJS@,$LTLIBOBJS,;t t -/@LIBAFTERIMAGEFILES@/r $LIBAFTERIMAGEFILES -s,@LIBAFTERIMAGEFILES@,,;t t -CEOF - -_ACEOF - - cat >>$CONFIG_STATUS <<\_ACEOF - # Split the substitutions into bite-sized pieces for seds with - # small command number limits, like on Digital OSF/1 and HP-UX. - ac_max_sed_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # Line after last line for current file. - ac_more_lines=: - ac_sed_cmds= - while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat - fi -fi # test -n "$CONFIG_FILES" - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_builddir$INSTALL ;; - esac - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s,@configure_input@,$configure_input,;t t -s,@srcdir@,$ac_srcdir,;t t -s,@abs_srcdir@,$ac_abs_srcdir,;t t -s,@top_srcdir@,$ac_top_srcdir,;t t -s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s,@builddir@,$ac_builddir,;t t -s,@abs_builddir@,$ac_abs_builddir,;t t -s,@top_builddir@,$ac_top_builddir,;t t -s,@abs_top_builddir@,$ac_abs_top_builddir,;t t -s,@INSTALL@,$ac_INSTALL,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi - -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -# -# CONFIG_HEADER section. -# - -# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where -# NAME is the cpp macro being defined and VALUE is the value it is being given. -# -# ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' -ac_dC=' ' -ac_dD=',;t' -# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='$,\1#\2define\3' -ac_uC=' ' -ac_uD=',;t' - -for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - # Do quote $f, to prevent DOS paths from being IFS'd. - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in - -_ACEOF - -# Transform confdefs.h into two sed scripts, `conftest.defines' and -# `conftest.undefs', that substitutes the proper values into -# config.h.in to produce config.h. The first handles `#define' -# templates, and the second `#undef' templates. -# And first: Protect against being on the right side of a sed subst in -# config.status. Protect against being in an unquoted here document -# in config.status. -rm -f conftest.defines conftest.undefs -# Using a here document instead of a string reduces the quoting nightmare. -# Putting comments in sed scripts is not portable. -# -# `end' is used to avoid that the second main sed command (meant for -# 0-ary CPP macros) applies to n-ary macro definitions. -# See the Autoconf documentation for `clear'. -cat >confdef2sed.sed <<\_ACEOF -s/[\\&,]/\\&/g -s,[\\$`],\\&,g -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp -t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp -: end -_ACEOF -# If some macros were called several times there might be several times -# the same #defines, which is useless. Nevertheless, we may not want to -# sort them, since we want the *last* AC-DEFINE to be honored. -uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines -sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs -rm -f confdef2sed.sed - -# This sed command replaces #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, -_ACEOF - -# Break up conftest.defines because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS -echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS -echo ' :' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.defines >/dev/null -do - # Write a limited-size here document to $tmp/defines.sed. - echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/defines.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail - rm -f conftest.defines - mv conftest.tail conftest.defines -done -rm -f conftest.defines -echo ' fi # grep' >>$CONFIG_STATUS -echo >>$CONFIG_STATUS - -# Break up conftest.undefs because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #undef templates' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.undefs >/dev/null -do - # Write a limited-size here document to $tmp/undefs.sed. - echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/undefs.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail - rm -f conftest.undefs - mv conftest.tail conftest.undefs -done -rm -f conftest.undefs - -cat >>$CONFIG_STATUS <<\_ACEOF - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - echo "/* Generated by configure. */" >$tmp/config.h - else - echo "/* $ac_file. Generated by configure. */" >$tmp/config.h - fi - cat $tmp/in >>$tmp/config.h - rm -f $tmp/in - if test x"$ac_file" != x-; then - if diff $ac_file $tmp/config.h >/dev/null 2>&1; then - { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 -echo "$as_me: $ac_file is unchanged" >&6;} - else - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - rm -f $ac_file - mv $tmp/config.h $ac_file - fi - else - cat $tmp/config.h - rm -f $tmp/config.h - fi -done -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - - -chmod 755 afterimage-libs diff --git a/graf2d/asimage/src/libAfterImage/configure.in b/graf2d/asimage/src/libAfterImage/configure.in deleted file mode 100644 index 2a479be9e122a..0000000000000 --- a/graf2d/asimage/src/libAfterImage/configure.in +++ /dev/null @@ -1,796 +0,0 @@ -dnl# -*- sh -*- -dnl# Process this file with autoconf to produce a configure script. -dnl# -dnl#Copyright (c) 1998 Michal Vitecek -dnl#Copyright (c) 2001,1998 Sasha Vasko -dnl#Copyright (c) 1998 Juergen Sawinski -dnl#Copyright (c) 1997 1998 Guylhem AZNAR - -AC_INIT(libAfterImage,1.20,as-bugs@afterstep.org,libAfterImage.tar) - -AC_CONFIG_HEADER(config.h:config.h.in) - -version=$PACKAGE_VERSION -version_major="1" -lib_name="LIBAFTERIMAGE" -lib_file_name=$PACKAGE_NAME - -dnl# Setup command-line options - -dnl# we need the standard prefixes defined early -test "x$prefix" = xNONE && prefix=$ac_default_prefix -test "x$exec_prefix" = xNONE && exec_prefix="$prefix" -eval "mandir=$mandir" -eval "libdir=$libdir" -eval "includedir=$includedir" - -dnl# compile-time switches -AC_ARG_ENABLE(i18n, [ --enable-i18n support I18N [no] ],enable_i18n=$enableval,enable_i18n="no") -AC_ARG_ENABLE(xlocale, [ --enable-xlocale using X_LOCALE [no] ],enable_xlocale=$enableval,enable_xlocale="no") -AC_ARG_WITH(locale, [ --with-locale=LOCALE locale name you want to use ],with_locale=$withval,with_locale="") -AC_ARG_ENABLE(staticlibs, [ --enable-staticlibs enable linking to libAfterImage statically [yes] ],enable_staticlibs=$enableval,enable_staticlibs="yes") -AC_ARG_ENABLE(sharedlibs, [ --enable-sharedlibs enable linking to libAfterImage dynamically [no] ],enable_sharedlibs=$enableval,enable_sharedlibs="no") - -AC_ARG_ENABLE(gdb, [ --enable-gdb add gdb symbols (-g) (for debugging) [no] ],enable_gdb=$enableval,enable_gdb="no") -AC_ARG_ENABLE(warn, [ --enable-warn turn on more compiler warnings (for debugging) [no] ],enable_warn=$enableval,enable_warn="no") -AC_ARG_ENABLE(gprof, [ --enable-gprof add gprof symbols (-pg) (for debugging) [no] ],enable_gprof=$enableval,enable_gprof="no") -AC_ARG_ENABLE(audit, [ --enable-audit memory usage audit (for debugging) [no] ],enable_audit=$enableval,enable_audit="no") -AC_ARG_ENABLE(shmimage, [ --enable-shmimage enable usage of MIT shared memory extention for image transfer [no] ],enable_shmimage=$enableval,enable_shmimage="no") -AC_ARG_ENABLE(shaping, [ --enable-shaping enable usage of MIT shaped windows extention [yes] ],enable_shaping=$enableval,enable_shaping="yes") -AC_ARG_ENABLE(glx, [ --enable-glx enable usage of GLX extention [no] ],enable_glx=$enableval,enable_glx="no") - -AC_ARG_ENABLE(mmx_optimization, - [ --enable-mmx-optimization enable utilization of MMX instruction set to speed up imaging operations [yes] ],enable_mmx_optimization=$enableval,enable_mmx_optimization="yes") - -AC_ARG_WITH(jpeg, [ --with-jpeg support JPEG image format [yes]]) -AC_ARG_WITH(jpeg_includes, [ --with-jpeg-includes=DIR use JPEG includes in DIR], jpeg_includes="$withval", jpeg_includes=no) -AC_ARG_WITH(builtin_jpeg, [ --with-builtin-jpeg use included JPEG library [no]],with_builtin_jpeg="$withval",with_builtin_jpeg=no) -AC_ARG_WITH(png, [ --with-png support PNG image format [yes]]) -AC_ARG_WITH(png_includes, [ --with-png-includes=DIR use PNG includes in DIR], png_includes="$withval", png_includes=no) -AC_ARG_WITH(builtin_png, [ --with-builtin-png use included PNG library [no]],with_builtin_png="$withval",with_builtin_png=no) -AC_ARG_WITH(builtin_zlib, [ --with-builtin-zlib use included libZ library (needed for PNG) [no]],with_builtin_zlib="$withval",with_builtin_zlib=no) -AC_ARG_WITH(tiff, [ --with-tiff support TIFF image format [yes]]) -AC_ARG_WITH(tiff_includes, [ --with-tiff-includes=DIR use TIFF includes in DIR], tiff_includes="$withval", tiff_includes=no) -AC_ARG_WITH(svg, [ --with-svg support SVG image format via librsvg [yes]]) - -AC_ARG_WITH(xpm, [ --with-xpm support XPM image format [yes]]) -dnl# libXPM should not be used as an obsolete software ! -with_builtin_xpm=$with_xpm -dnl# AC_ARG_WITH(builtin_xpm, [ --with-builtin-xpm use builtin XPM parsing/handling instead of libXpm [yes]]) -dnl# AC_ARG_WITH(xpm_includes, [ --with-xpm-includes=DIR use libXpm includes in DIR( when builtin XPM handling is disabled )], xpm_includes="$withval", xpm_includes=no) - -dnl# standard libgif/ungif should not be used and considered obsolete! -AC_ARG_WITH(ungif, [ --with-ungif support Uncompressed GIF image format using libungif [no]],with_ungif="$withval",with_ungif=no) -AC_ARG_WITH(gif, [ --with-gif support GIF image format using libgif [no]],with_gif="$withval",with_gif=no) -AC_ARG_WITH(gif_includes, [ --with-gif-includes=DIR use GIF includes in DIR], gif_includes="$withval", gif_includes=no) -AC_ARG_WITH(builtin_gif, [ --with-builtin-gif support Uncompressed GIF image format using builtin libgif [yes]],with_builtin_gif="$withval",with_builtin_gif=yes) - - -AC_ARG_WITH(ttf, [ --with-ttf support True Type Fonts via FreeType library [yes]]) -AC_ARG_WITH(ttf_includes, [ --with-ttf-includes=DIR use FreeType includes in DIR], ttf_includes="$withval", ttf_includes=no) - -AC_ARG_WITH(afterbase, [ --with-afterbase use libAfterBase library of basic functionality [yes]],with_afterbase="$withval",with_afterbase=yes) -AC_ARG_WITH(afterbase_includes, [ --with-afterbase-includes=DIR use libAfterBase includes in DIR],afterbase_includes="$withval",afterbase_includes=no) - -dnl# Check for compiler tools - -AC_PROG_CC -AC_PROG_LN_S -dnl# AC_SUBST(CC) -dnl# AC_SUBST(GCC) - - -AC_CYGWIN -AC_CANONICAL_TARGET - -RDYNAMIC="-rdynamic" - -case "$target" in - *i?86*OpenUNIX*) - RDYNAMIC="-Wl,-Bexport" - ;; - *i?86*sco*) - RDYNAMIC="-Wl,-Bexport" - ;; - *aix*) - RDYNAMIC="-Wl,-bexpall" - ;; - *i?86*freebsd*) - RDYNAMIC="" - ;; - hppa*) - RDYNAMIC="-Wl,-E" - ;; - i?86*solaris*) - RDYNAMIC="" - ;; - sparc*solaris*) - RDYNAMIC="-Wl,-export-dynamic" - ;; - *-apple-darwin*) - RDYNAMIC="-Wl,-Sn" - ;; - *ppc* | *powerpc*) - RDYNAMIC="" - ;; - *) -esac - -if test "x$CYGWIN" = "xno" -a "x$GCC" = "xyes" ; then - if test -z "`echo $CFLAGS | grep '\-fPIC' 2> /dev/null`" ; then - CFLAGS="$CFLAGS -fPIC" - fi -fi - - -if test "x$FROM_AFTERSTEP_CONFIGURE" = "xyes"; then - -dnl# AfterSTep already checked everything for us - aaa=bbb - dnl# AC_PROG_INSTALL - AC_SUBST(INSTALL) - AC_SUBST(INSTALL_PROGRAM) - AC_SUBST(INSTALL_DATA) - AC_SUBST(INSTALL_LIB) - AC_SUBST(RANLIB) - AC_SUBST(RM) - AC_SUBST(MV) - AC_SUBST(CP) - AC_SUBST(MKDIR) - AC_SUBST(PERL) - AC_SUBST(FIND) - AC_SUBST(XARGS) - AC_SUBST(LDCONFIG) - AC_SUBST(LEX) - AC_SUBST(LEXLIB) - AC_SUBST(YACC) - if test "x$have_shmimage" = "xyes"; then - AC_DEFINE(XSHMIMAGE) - fi - if test "x$have_shaping" = "xyes"; then - AC_DEFINE(SHAPE) - fi - -else - -dnl# we are alone - have to do all the checks ourselves : - dnl# Add -Wall - if test "x$GCC" = "xyes"; then - if test -z "`echo $CFLAGS | grep '\-Wall' 2> /dev/null`" ; then - CFLAGS="$CFLAGS -Wall" - fi - fi - - dnl# Add -fPIC for IA64 compilation - - dnl# Add -g - if test "x$enable_gdb" = "xyes"; then - if ! test -n "`echo $CFLAGS' ' | grep '\-g ' 2> /dev/null`" ; then - CFLAGS="$CFLAGS -g" - fi - else - DIRTY_CFLAGS="$CFLAGS" - CFLAGS="-DNO_DEBUG_OUTPUT" - for f in $DIRTY_CFLAGS; do - if test "x$f" != "x-g"; then - CFLAGS="$CFLAGS $f" - fi - done - fi - dnl# Add -pg - if test "x$enable_gprof" = "xyes"; then - CFLAGS="$CFLAGS -pg" - LDFLAGS="$LDFLAGS -pg" - fi - dnl# Add lots more warnings - if test "x$enable_warn" = "xyes"; then - CFLAGS="$CFLAGS -Wuninitialized -Wwrite-strings -Wcast-qual -Wbad-function-cast -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wconversion -Wcomment -Wcast-align -Winline -Wshadow -Wredundant-decls" - fi - AC_PROG_INSTALL - dnl# if the path to the install program is relative, make it absolute - currdir=`pwd` - INSTALL=`echo $INSTALL|sed -e "s@\^\.\.@${currdir}@" -e "s@^autoconf@${currdir}/autoconf@"` - INSTALL_PROGRAM=`echo $INSTALL_PROGRAM|sed -e "s@\^\.\.@${currdir}@" -e "s@^autoconf@${currdir}/autoconf@"` - INSTALL_DATA=`echo $INSTALL_DATA|sed -e "s@\^\.\.@${currdir}@" -e "s@^autoconf@${currdir}/autoconf@"` - INSTALL_LIB=`echo $INSTALL_LIB|sed -e "s@\^\.\.@${currdir}@" -e "s@^autoconf@${currdir}/autoconf@"` - - AC_PROG_RANLIB - AC_PATH_PROG(RM, rm, rm) - AC_PATH_PROG(MV, mv, mv) - AC_PATH_PROG(CP, cp, cp) - AC_PATH_PROG(MKDIR, mkdir, mkdir) - AC_PATH_PROG(PERL, perl, perl) - AC_PATH_PROG(FIND, find, find) - AC_PATH_PROG(XARGS, xargs, xargs) - AC_PATH_PROG(LDCONFIG, ldconfig, ldconfig, $PATH:/sbin:/usr/local/sbin) -fi - -if test "x$enable_gdb" = "xno"; then - DIRTY_CFLAGS="$CFLAGS" - CFLAGS="-O3" - for f in $DIRTY_CFLAGS; do - if test "x$f" != "x-O2" -a "x$f" != "x-O3" -a "x$f" != "x-O"; then - CFLAGS="$CFLAGS $f" - fi - done -fi - - -MMX_CFLAGS="-mmmx -Winline" -have_mmx_intrinsics=no - -dnl# Check for MMX : -if test "x$enable_mmx_optimization" = "xyes"; then - AC_MSG_CHECKING(for MMX support) - - save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $MMX_CFLAGS" -AC_COMPILE_IFELSE([ -#if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)) -#error "Need GCC >= 3.4 for MMX intrinsics" -#endif -#include -int main () { - __m64 v = _mm_cvtsi32_si64 (1); - __m64 w = _mm_slli_si64 (v, 1); - v = _mm_add_pi32 (v, w); /* paddd */ - v = _mm_srl_pi32 (v, w); /* psrld */ - return _mm_cvtsi64_si32 (v); -}], have_mmx_intrinsics=yes) - - AC_MSG_RESULT($have_mmx_intrinsics) - CFLAGS=$save_CFLAGS -fi - -if test $have_mmx_intrinsics = yes ; then - AC_DEFINE(HAVE_MMX,1,[Define if CPU supports MMX instructions]) -else - MMX_CFLAGS= -fi -AC_SUBST(MMX_CFLAGS) - -dnl# Check for X : -dnl# check for X, if top level configure script did not do that yet : -afterimage_x_support=yes -if test "x$PATH_XTRA_CHECKED" != "xyes"; then - AC_PATH_XTRA -else - if test "x$have_x" != "xyes"; then - AC_DEFINE(X_DISPLAY_MISSING) - afterimage_x_support=no - fi - -fi - -user_ldflags=$LDFLAGS - -if test "x$have_x" = "xyes"; then - x_libs="$X_LIBS $X_EXTRA_LIBS $X_PRE_LIBS" - if test "x$user_ldflags" = "x"; then - full_x_libs=$x_libs - else - full_x_libs="$user_ldflags $x_libs" - fi - AC_CHECK_LIB(X11, XOpenDisplay, [x_libs="-lX11 $x_libs"],,$full_x_libs) -fi - - - -dnl# some standard checks : -dnl# let's check for endiannes of our box -AC_C_BIGENDIAN -AC_C_INLINE -AC_CHECK_TYPES([long long]) - -dnl# Check for headers -AC_HEADER_TIME -AC_CHECK_HEADERS(sys/wait.h sys/time.h malloc.h stdlib.h unistd.h stddef.h stdarg.h errno.h) - -dnl# Check for X shaped window extension -have_shmimage=no -have_xext_lib=no -if test "x$enable_shmimage" = "xyes"; then - AC_CHECK_LIB(Xext, XShmCreateImage, [have_shmimage=yes],,$full_x_libs) - if test "x$have_shmimage" = "xyes"; then - AC_CHECK_HEADER(sys/ipc.h,,[have_shmimage=no]) - fi - if test "x$have_shmimage" = "xyes"; then - AC_CHECK_HEADER(sys/shm.h,,[have_shmimage=no]) - fi - if test "x$have_shmimage" = "xyes"; then - have_xext_lib=yes - AC_DEFINE(XSHMIMAGE,1,[Define if support for shared memory XImages is available]) - fi -fi - -dnl# Check for X shaped window extension -HAVESHAPE="NOSHAPE" -if test "x$enable_shaping" = "xyes"; then - AC_CHECK_LIB(Xext, XShapeCombineMask, [have_xext_lib=yes;AC_DEFINE(SHAPE,1,Support for shaped windows)],,$full_x_libs) -fi - -if test "x$enable_glx" = "xyes"; then - AC_CHECK_LIB(GL, glDrawPixels, [x_libs="$x_libs -lGL";AC_DEFINE(HAVE_GLX,1,Support for OpenGL extention)],,$full_x_libs) -fi - - -if test "x$have_xext_lib" = "xyes"; then - x_libs="$x_libs -lXext" -fi - -dnl# Check for graphics libraries : - -image_format="xpm" - -AFTERIMAGE_LIBS=$x_libs - -if test "$with_xpm" = no; then - have_xpm=disabled -else - if test "$with_builtin_xpm" = no; then - SAVED_CFLAGS=$CPPFLAGS - if test "x$xpm_includes" != "xno"; then - XPM_CFLAGS="-I$xpm_includes" - CPPFLAGS="$CPPFLAGS $XPM_CFLAGS" - fi - have_libxpm=no - AC_CHECK_HEADER(xpm.h,have_libxpm=yes) - if test "x$have_libxpm" = "xno"; then - AC_CHECK_HEADER(X11/xpm.h,have_libxpm_x11="yes") - if test "x$have_libxpm_x11" = "xyes"; then - AC_DEFINE(HAVE_LIBXPM_X11,1,[Define if support for XPM images should be through libXpm library in Xlib]) - have_libxpm=yes - fi - fi - if test "x$have_libxpm" = "xyes"; then - AC_DEFINE(HAVE_XPM,1,[Define if support for XPM images is desired]) - AC_DEFINE(HAVE_LIBXPM,1,[Define if support for XPM images should be through libXpm]) - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lXpm" - fi - CPPFLAGS=$SAVED_CFLAGS - else - AC_DEFINE(HAVE_XPM,1,[Define if support for XPM images is desired]) - XPM_CFLAGS= - fi -fi -AC_SUBST(XPM_CFLAGS) - -JPEG_OBJS= -ZLIB_OBJS= -PNG_OBJS= - -have_jpeg= - -if test "$with_jpeg" = no; then - have_jpeg=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "x$jpeg_includes" != "xno"; then - JPEG_CFLAGS="-I$jpeg_includes" - CPPFLAGS="$CPPFLAGS $JPEG_CFLAGS" - fi - if test "with_builtin_jpeg" = yes -a ! -f libjpeg/jpeglib.h; then - with_builtin_jpeg=no - fi - if test "$with_builtin_jpeg" = no; then - AC_CHECK_HEADER(jpeglib.h,have_jpeg=yes) - fi - if test "$have_jpeg" = yes; then - AC_DEFINE(HAVE_JPEG,1,[Define if libjpeg is available]) - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -ljpeg" - else - AC_MSG_CHECKING(built-in JPEG library) - if test -f libjpeg/jpeglib.h; then - JPEG_OBJS='$(LIBJPEG_OBJS)' - AC_DEFINE(HAVE_JPEG,1,[Define if libjpeg is available]) - AC_DEFINE(HAVE_BUILTIN_JPEG,1,[Define if using builtin libjpeg]) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - fi - CPPFLAGS=$SAVED_CFLAGS -fi -AC_SUBST(JPEG_CFLAGS) - -dnl# these check are needed by built-in jpeg library : -AC_DEFINE(HAVE_PROTOTYPES,1,We always use function prototypes - not supporting old compilers) -AC_CHECK_TYPE(unsigned char) -AC_CHECK_TYPE(unsigned short) -AC_C_CONST -AC_C_CHAR_UNSIGNED - -have_png=no -have_zlib=no - -if test "$with_png" = no; then - have_png=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "$png_includes" != no; then - PNG_CFLAGS="-I$png_includes" - CPPFLAGS="$CPPFLAGS $PNG_CFLAGS" - fi - if test "$with_builtin_png" = yes -a ! -f libpng/png.h; then - with_builtin_png=no - fi - if test "$with_builtin_zlib" = yes -a ! -f zlib/zlib.h; then - with_builtin_zlib=no - fi - - if test "$with_builtin_png" = no; then - AC_CHECK_HEADER(png.h,[have_png=yes with_builtin_zlib=no]) - fi - if test "$with_builtin_zlib" = no; then - AC_CHECK_HEADERS(zlib.h,[have_zlib=yes],[have_zlib=no]) - fi - if test "$have_png" = yes; then - AC_MSG_CHECKING(for png_get_sRGB in png.h) - AC_EGREP_HEADER(png_get_sRGB,png.h,,have_png=no) - AC_MSG_RESULT($have_png) - fi - if test "$have_png" = yes; then - AC_DEFINE(HAVE_PNG,1,[Define if libpng is available]) - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lpng" - image_format="png" - else - AC_MSG_CHECKING(built-in PNG library) - if test -f libpng/png.h; then - PNG_OBJS='$(LIBPNG_OBJS)' - AC_DEFINE(HAVE_PNG,1,[Define if libpng is available]) - AC_DEFINE(HAVE_BUILTIN_PNG,1,[Define if using builtin libpng]) - AC_MSG_RESULT(yes) - if test "$have_zlib" = no; then - AC_MSG_CHECKING(built-in ZLIB library) - if test -f zlib/zlib.h; then - ZLIB_OBJS='$(ZLIB_OBJS)' - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - fi - image_format="png" - have_png=yes - else - AC_MSG_RESULT(no) - fi - fi - CPPFLAGS=$SAVED_CFLAGS -fi -AC_SUBST(PNG_CFLAGS) -dnl# This is required by built in versions of zlib and libpng : - -dnl# Test for libungif first : -have_gif=no -if test "$with_gif$with_ungif" = nono; then - have_gif=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "$gif_includes" != no; then - GIF_CFLAGS="-I$gif_includes" - CPPFLAGS="$CPPFLAGS $GIF_CFLAGS" - fi - AC_CHECK_HEADER(gif_lib.h,have_gif=yes) - CPPFLAGS=$SAVED_CFLAGS - if test "x$have_gif" = "xyes"; then - AC_DEFINE(HAVE_GIF,1,[Define if libgif is available]) - if test "$with_gif" = no; then - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lungif" - else - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lgif" - fi - fi -fi - -if test "x$have_gif" != "xyes"; then - if test "x$with_builtin_gif" = "xyes"; then - AC_MSG_CHECKING(using built-in UNGIF library) - if test -f libungif/gif_lib.h; then - UNGIF_OBJS='$(LIBUNGIF_OBJS)' - AC_DEFINE(HAVE_GIF,1,[Define if libgif/ungif is available]) - AC_DEFINE(HAVE_BUILTIN_UNGIF,1,[Define if using builtin libgif]) - AC_MSG_RESULT(yes) - have_gif=yes - else - AC_MSG_RESULT(no) - fi - fi -fi - -AC_SUBST(GIF_CFLAGS) - -dnl# Test for libtiff : - -if test "$with_tiff" = no; then - have_tiff=disabled -else - SAVED_CFLAGS=$CPPFLAGS - if test "$tiff_includes" != no; then - TIFF_CFLAGS="-I$tiff_includes" - CPPFLAGS="$CPPFLAGS $TIFF_CFLAGS" - fi - AC_CHECK_HEADER(tiffio.h,[AC_DEFINE(HAVE_TIFF,1,[Define if libtiff is available]) AFTERIMAGE_LIBS="-ltiff $AFTERIMAGE_LIBS" have_tiff=yes]) - CPPFLAGS=$SAVED_CFLAGS -fi -AC_SUBST(TIFF_CFLAGS) - -if test "$have_tiff" = yes -o "$have_png" = yes ; then - if test "x$ZLIB_OBJS" = "x" -a "$have_zlib" = yes; then - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lz" - fi -fi - -have_svg= -if test "$with_svg" = no; then - have_svg=disabled -else - if test -z "$PKG_CONFIG"; then - AC_PATH_PROG(PKG_CONFIG, pkg-config,no) - fi - if test "$PKG_CONFIG" = "no" ; then - AC_MSG_CHECKING(if librsvg 2.0 is available) - AC_MSG_RESULT(pkg-config is not found. Cannot check for librsvg 2.0.) - have_svg=no - else - have_svg=yes - pkg_modules="librsvg-2.0 >= 2.0.0" - - PKG_CHECK_MODULES(SVG,[$pkg_modules],,[have_svg=no]) - - if test "x$have_svg" = "xyes"; then - AC_DEFINE(HAVE_SVG,1,librsvg v.2.0 or higher is available ) - AFTERIMAGE_LIBS="$SVG_LIBS $AFTERIMAGE_LIBS" - fi - fi -fi - -AC_SUBST(SVG_CFLAGS) - -dnl# we always need libm since we now call exp() in gaussian blur -AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lm" - -dnl# check for libfreetype - -TTF_INCLUDES= - -if test "x$with_ttf" = "xno"; then - have_ttf=disabled -else - if test "x$ttf_includes" = "xno"; then - AC_MSG_CHECKING(headers required by TTF support) - if freetype-config --cflags >/dev/null ;then - present_incs="$CCFLAGS $x_includes"; - for l in `freetype-config --cflags` ; do - inc_found=no - for p in `echo "$present_incs"` ; do - if test "x$l" = "x$p" ; then - inc_found=yes; - fi; - if test "x$l" = "x-I$p" ; then - inc_found=yes; - fi; - done; - if test "x$inc_found" != "xyes" ; then - TTF_INCLUDES="$TTF_INCLUDES $l" ; - fi; - done; - AC_MSG_RESULT($TTF_INCLUDES) - saved_CPPFLAGS=$CPPFLAGS - saved_CFLAGS=$CFLAGS - CPPFLAGS="$TTF_INCLUDES $CPPFLAGS" - CFLAGS="$CFLAGS $TTF_INCLUDES $XPM_CFLAGS $JPEG_CFLAGS $PNG_CFLAGS $GIF_CFLAGS $TIFF_CFLAGS $SVG_CFLAGS $X_CFLAGS" - have_ft2build=no - AC_CHECK_HEADERS(ft2build.h,[have_ft2build=yes]) - AC_MSG_CHECKING( freetype/freetype.h ) - have_ttf=no - have_freetype_freetype=no - have_freetype=no - AC_EGREP_HEADER(FT_Face,freetype/freetype.h, - [have_freetype_freetype=yes], - [AC_MSG_RESULT(no);AC_MSG_CHECKING(freetype.h); \ - AC_EGREP_HEADER(FT_Face,freetype.h, - [have_freetype=yes], AC_MSG_RESULT(no))] - ) - if test "x$have_ft2build" = "xno" ; then - if test "x$have_freetype_freetype" = "xyes" ; then - AC_TRY_RUN([#include - int main(){FT_Face f; return 0;}], - [have_ttf=yes],AC_MSG_RESULT(no)) - elif test "x$have_freetype" = "xyes" ; then - AC_TRY_RUN([#include - int main(){FT_Face f; return 0;}], - [have_ttf=yes],AC_MSG_RESULT(no)) - fi; - elif test "x$have_freetype_freetype" = "xyes" ; then - AC_TRY_RUN([#include - #include - int main(){FT_Face f; return 0;}], - [have_ttf=yes],AC_MSG_RESULT(no)) - elif test "x$have_freetype" = "xyes" ; then - AC_TRY_RUN([#include - #include - int main(){FT_Face f; return 0;}], - [have_ttf=yes],AC_MSG_RESULT(no)) - fi; - if test "x$have_ttf" = "xyes" ; then - AC_DEFINE(HAVE_FREETYPE,1,[Define if libFreeType is available]) - if test "x$have_freetype_freetype" = "xyes" ; then - AC_DEFINE(HAVE_FREETYPE_FREETYPE,1,[Define if libFreeType has freetype.h in freetype/ ]) - fi; - AC_MSG_RESULT(yes) - fi; - CPPFLAGS=$saved_CPPFLAGS - CFLAGS=$saved_CFLAGS - else - enable_ttf=no ; - AC_MSG_RESULT(none found, ttf disabled) - echo "You have to install FreeType libary in order to be able to use TTF fonts." - have_ttf=no - fi; - else - TTF_INCLUDES=$ttf_includes - AC_DEFINE(HAVE_FREETYPE,1,[Define if libFreeType is available]) - have_ttf=yes - fi - if test "$have_ttf" = yes; then - AFTERIMAGE_LIBS="`freetype-config --libs` $AFTERIMAGE_LIBS" - fi -fi; -AC_SUBST(TTF_INCLUDES) - -AC_SUBST(JPEG_OBJS) -AC_SUBST(ZLIB_OBJS) -AC_SUBST(PNG_OBJS) -AC_SUBST(UNGIF_OBJS) - -AFTERIMAGE_LIBS_EXTERNAL=$AFTERIMAGE_LIBS -AC_SUBST(AFTERIMAGE_LIBS_EXTERNAL) - -USE_DEFAULT_AFTERBASE=0 -AFTERBASE_INCS_PATH= -if test "x$with_afterbase" != "xno"; then - AC_MSG_CHECKING(libAfterBase headers in ../libAfterBase) - have_afterbase=yes - if test "x$afterbase_includes" = "xno"; then - if test -r "../libAfterBase/astypes.h"; then - AC_MSG_RESULT(yes) - AFTERBASE_INCS_PATH="../" - else - AC_MSG_RESULT(no) - AC_CHECK_HEADER(libAfterBase/astypes.h,[USE_DEFAULT_AFTERBASE=1],[have_afterbase=no]) - fi - else - AFTERBASE_INCS_PATH="$afterbase_includes/" - AC_MSG_RESULT($AFTERBASE_INCS_PATH) - fi -else - AC_MSG_CHECKING(libAfterBase) -fi - -AFTERBASE_C=afterbase.o -HAVE_AFTERBASE_FLAG=0 -if test "x$have_afterbase" = "xyes"; then - HAVE_AFTERBASE_FLAG=1 - AFTERBASE_C= - if test "x$CYGWIN" = "xno" -a "x$GCC" = "xyes" ; then -dnl# rdynamic is only useable if we have libAfterBase's backtrace functionality - user_ldflags="$user_ldflags $RDYNAMIC" - fi - if test "x$have_x" != "xyes" -a "x$have_gif" = "xyes"; then - AFTERIMAGE_LIBS="$AFTERIMAGE_LIBS -lAfterBase" - else - AFTERIMAGE_LIBS="-lAfterBase $AFTERIMAGE_LIBS" - fi - if test -r "../libAfterBase/astypes.h"; then - AFTERIMAGE_APPS_LIBS="-L../ -L../../libAfterBase -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_TEST_LIBS="-L./ -L../libAfterBase -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_LIB_LIBS="-L./ -L../libAfterBase $AFTERIMAGE_LIBS" - else - AFTERIMAGE_APPS_LIBS="-L../ -L$libdir -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_TEST_LIBS="-L./ -L$libdir -lAfterImage $AFTERIMAGE_LIBS" - AFTERIMAGE_LIB_LIBS="-L./ -L$libdir $AFTERIMAGE_LIBS" - fi - AC_DEFINE(HAVE_AFTERBASE,1,[Define if libAfterBase is available]) -else - AFTERIMAGE_APPS_LIBS="-L../ -lAfterImage $AFTERIMAGE_LIBS_EXTERNAL" - AFTERIMAGE_TEST_LIBS="-L./ -lAfterImage $AFTERIMAGE_LIBS_EXTERNAL" - AFTERIMAGE_LIB_LIBS="-L./ $AFTERIMAGE_LIBS_EXTERNAL" - if test "$with_afterbase" = "no"; then - AC_MSG_RESULT(disabled) - fi - AC_HEADER_DIRENT - AC_CHECK_HEADERS(sys/dirent.h) -fi -AC_SUBST(AFTERBASE_INCS_PATH) -AC_SUBST(USE_DEFAULT_AFTERBASE) -AC_SUBST(HAVE_AFTERBASE_FLAG) -AC_SUBST(AFTERBASE_C) -AC_SUBST(have_afterbase) -AC_SUBST(AFTERIMAGE_APPS_LIBS) -AC_SUBST(AFTERIMAGE_TEST_LIBS) -AC_SUBST(AFTERIMAGE_LIB_LIBS) -AC_SUBST(afterimage_x_support) - -dnl# finalizing libs listing : - -CLEAN_AFTERIMAGE_LIBS= -for L in $AFTERIMAGE_LIBS; do - if test "$L" != "-L$libdir"; then - CLEAN_AFTERIMAGE_LIBS="$CLEAN_AFTERIMAGE_LIBS $L" - fi -done -AFTERIMAGE_LIBS="-L$libdir -lAfterImage $CLEAN_AFTERIMAGE_LIBS" -AC_SUBST(AFTERIMAGE_LIBS) - -if test "x$enable_staticlibs" = "xyes"; then - LIBPROG='$(LIB_STATIC)' - LIBINSTALL="install.static" - LIBUNINSTALL="install.static" -else - enable_sharedlibs="yes" -fi -if test "x$enable_sharedlibs" = "xyes"; then - if test "x$CYGWIN" = "xyes" ; then - tmp='$(LIB_SHARED_CYG)' - tmp2='install.cyg' - else - tmp='$(LIB_SHARED)' - tmp2='install.dyn' - fi - LIBPROG="$LIBPROG $tmp" - LIBINSTALL="$LIBINSTALL $tmp2" - LIBUNINSTALL="uninstall.static un$tmp2" -fi - -dnl# define X_LOCALE. need Linux, NetBSD and etc. -if test "x$enable_xlocale" = "xyes"; then - DEFINE_XLOCALE="-DX_LOCALE" -fi - -dnl# Translate enable_* from "yes/no" to "1/0" (for configure.h) - -if test "x$enable_i18n" = "xyes"; then AC_DEFINE(I18N,1,[Define if locale support in X is needed]) fi -if test "x$enable_audit" = "xyes"; then AC_DEFINE(DEBUG_ALLOCS,1,[Define if memory allocation logging and debugging is desired]) fi - -dnl# Variable strings declaration - -AC_SUBST(image_format) - -AC_SUBST(CFLAGS) -AC_SUBST(version) -AC_SUBST(version_major) -AC_SUBST(lib_name) -AC_SUBST(lib_file_name) -AC_SUBST(with_locale) -AC_SUBST(user_ldflags) -AC_SUBST(x_libs) -AC_SUBST(X_CFLAGS) -AC_SUBST(LIBPROG) -AC_SUBST(LIBINSTALL) -AC_SUBST(DEFINE_XLOCALE) -AC_SUBST(PERL) - -dnl# Write results -dnl# Common parts of the Makefile - -LIBAFTERIMAGEFILES=.shared -AC_SUBST_FILE(LIBAFTERIMAGEFILES) - -APPSDEPS= -if test -d apps ; then - APPSDEPS='$(APPS_DEPS)' - AC_CONFIG_FILES([apps/Makefile]) -fi - -if test -d aftershow ; then - AC_CONFIG_FILES([aftershow/Makefile]) -fi - -AC_SUBST(APPSDEPS) - -AC_OUTPUT(Makefile \ -afterbase.h \ -afterimage-libs \ -afterimage-config) - -chmod 755 afterimage-libs diff --git a/graf2d/asimage/src/libAfterImage/draw.c b/graf2d/asimage/src/libAfterImage/draw.c index 4ce1f01dc4717..b1606bd1c3fbe 100644 --- a/graf2d/asimage/src/libAfterImage/draw.c +++ b/graf2d/asimage/src/libAfterImage/draw.c @@ -20,12 +20,6 @@ #undef DEBUG_ELLIPS -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #ifdef _WIN32 #define Long64_t __int64 #else @@ -38,11 +32,7 @@ #include #include #include -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #include "asvisual.h" #include "asimage.h" #include "draw.h" @@ -1016,8 +1006,10 @@ asim_apply_path( ASDrawContext *ctx, int start_x, int start_y, Bool fill, int fi LOCAL_DEBUG_CALLER_OUT( "start_x = %d, start_y = %d, fill = %d, fill_start_x = %d, fill_start_y = %d", start_x, start_y, fill, fill_start_x, fill_start_y ); + (void)start_x; + (void)start_y; // silence unused variable warning - /* TODO : contour tracing functionality : */ + /* TODO : contour tracing functionality : */ if( fill ) asim_flood_fill( ctx, fill_start_x, fill_start_y, 0, fill_threshold==0?CTX_DEFAULT_FILL_THRESHOLD:fill_threshold ); diff --git a/graf2d/asimage/src/libAfterImage/export.c b/graf2d/asimage/src/libAfterImage/export.c index 099dbe61f9238..1679390c50088 100644 --- a/graf2d/asimage/src/libAfterImage/export.c +++ b/graf2d/asimage/src/libAfterImage/export.c @@ -19,11 +19,6 @@ */ #undef LOCAL_DEBUG -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif #ifdef HAVE_PNG /* Include file for users of png library. */ @@ -69,11 +64,7 @@ #include /* is used for the optional error recovery mechanism */ -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #ifdef HAVE_GIF # include @@ -482,8 +473,8 @@ ASImage2png_int ( ASImage *im, void *data, png_rw_ptr write_fn, png_flush_ptr fl static const ASPngExportParams defaults = { ASIT_Png, EXPORT_ALPHA, -1 }; png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); - if ( png_ptr != NULL ) - if( (info_ptr = png_create_info_struct(png_ptr)) != NULL ) + if (png_ptr != NULL) + if( (info_ptr = png_create_info_struct(png_ptr)) != NULL ) if( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_info_struct(png_ptr, (png_infopp) &info_ptr); @@ -669,7 +660,8 @@ void asim_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) void asim_png_flush_data(png_structp png_ptr) { - /* nothing to do really, but PNG requires it */ + (void)png_ptr; // silence unused variable warning + /* nothing to do really, but PNG requires it */ } @@ -882,8 +874,11 @@ ASImage2jpeg( ASImage *im, const char *path, ASImageExportParams *params ) Bool ASImage2xcf ( ASImage *im, const char *path, ASImageExportParams *params ) { - /* More stuff */ - XcfImage *xcf_im = NULL; + (void)im; + (void)path; + (void)params; // silence unused variable warning + /* More stuff */ + XcfImage *xcf_im = NULL; START_TIME(started); SHOW_PENDING_IMPLEMENTATION_NOTE("XCF"); @@ -906,7 +901,10 @@ ASImage2xcf ( ASImage *im, const char *path, ASImageExportParams *params ) Bool ASImage2ppm ( ASImage *im, const char *path, ASImageExportParams *params ) { - START_TIME(started); + (void)im; + (void)path; + (void)params; // silence unused variable warning + START_TIME(started); SHOW_PENDING_IMPLEMENTATION_NOTE("PPM"); SHOW_TIME("image export",started); return False; @@ -919,7 +917,10 @@ ASImage2ppm ( ASImage *im, const char *path, ASImageExportParams *params ) Bool ASImage2ico ( ASImage *im, const char *path, ASImageExportParams *params ) { - START_TIME(started); + (void)im; + (void)path; + (void)params; // silence unused variable warning + START_TIME(started); SHOW_PENDING_IMPLEMENTATION_NOTE("ICO"); SHOW_TIME("image export",started); return False; @@ -934,8 +935,8 @@ Bool ASImage2gif( ASImage *im, const char *path, ASImageExportParams *params ) GifFileType *gif = NULL ; ColorMapObject *gif_cmap ; Bool dont_save_cmap = False ; - static const ASGifExportParams defaultsGif = { ASIT_Gif,EXPORT_ALPHA|EXPORT_APPEND, 3, 127, 10 }; - ASImageExportParams defaults; + static const ASGifExportParams defaultsGif = {ASIT_Gif, EXPORT_ALPHA | EXPORT_APPEND, 3, 127, 10, 0}; + ASImageExportParams defaults; ASColormap cmap; int *mapped_im ; int y ; @@ -1120,6 +1121,7 @@ Bool ASImage2gif( ASImage *im, const char *path, ASImageExportParams *params ) if (outfile) { #if (GIFLIB_MAJOR>=5) + errcode=E_GIF_SUCCEEDED; gif = EGifOpenFileHandle(fileno(outfile), &errcode); if (errcode != E_GIF_SUCCEEDED) ASIM_PrintGifError(errcode); @@ -1221,17 +1223,17 @@ ASImage2tiff( ASImage *im, const char *path, ASImageExportParams *params) TIFF *out; static const ASTiffExportParams defaultsTiff = { ASIT_Tiff, 0, (CARD32)-1, TIFF_COMPRESSION_NONE, 100, 0 }; ASImageExportParams defaults; - uint16 photometric = PHOTOMETRIC_RGB; - tsize_t linebytes, scanline; - ASImageDecoder *imdec ; - CARD32 *r, *g, *b, *a ; - unsigned char* buf; - CARD32 row ; - Bool has_alpha ; - int nsamples = 3 ; - START_TIME(started); - - if( params == NULL ) { + uint16_t photometric = PHOTOMETRIC_RGB; + tsize_t linebytes, scanline; + ASImageDecoder *imdec; + CARD32 *r, *g, *b, *a; + unsigned char *buf; + CARD32 row; + Bool has_alpha; + int nsamples = 3; + START_TIME(started); + + if (params == NULL) { defaults.type = defaultsTiff.type; defaults.tiff = defaultsTiff; params = &defaults ; @@ -1267,21 +1269,21 @@ ASImage2tiff( ASImage *im, const char *path, ASImageExportParams *params) return False; } - TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) im->width); - TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) im->height); - TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32_t)im->width); + TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32_t)im->height); + TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nsamples); if (has_alpha) { - uint16 v[1]; - v[0] = EXTRASAMPLE_UNASSALPHA; - TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v); + uint16_t v[1]; + v[0] = EXTRASAMPLE_UNASSALPHA; + TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v); } TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - if( params->tiff.compression_type == -1 ) - params->tiff.compression_type = defaultsTiff.compression_type ; + if (params->tiff.compression_type == (unsigned int)-1) + params->tiff.compression_type = defaultsTiff.compression_type ; TIFFSetField(out, TIFFTAG_COMPRESSION, params->tiff.compression_type); switch (params->tiff.compression_type ) { @@ -1359,6 +1361,8 @@ Bool ASImage2tiff( ASImage *im, const char *path, ASImageExportParams *params ) { SHOW_UNSUPPORTED_NOTE("TIFF",path); + (void)im; + (void)params; // silence unused variable warning return False ; } #endif /* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */ diff --git a/graf2d/asimage/src/libAfterImage/imencdec.c b/graf2d/asimage/src/libAfterImage/imencdec.c index ee0f23af4989c..927d9efff3746 100644 --- a/graf2d/asimage/src/libAfterImage/imencdec.c +++ b/graf2d/asimage/src/libAfterImage/imencdec.c @@ -25,12 +25,6 @@ #undef DEBUG_RECTS2 #endif -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #include #ifdef DO_CLOCKING #if TIME_WITH_SYS_TIME @@ -58,11 +52,7 @@ #include #endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #include "asvisual.h" #include "blender.h" #include "asimage.h" @@ -125,13 +115,13 @@ Bool create_image_xim( ASVisual *asv, ASImage *im, ASAltImFormats format ) format = ASA_ScratchXImage ; do_alpha = True ; } + (void)do_alpha; // silence unused variable warning - if( format == ASA_ScratchXImage || format == ASA_ScratchMaskXImage ) - { - scratch = True ; + if (format == ASA_ScratchXImage || format == ASA_ScratchMaskXImage) { + scratch = True ; format = (format - ASA_ScratchXImage ) + ASA_XImage ; - } - dst = (format == ASA_MaskXImage )? &(im->alt.mask_ximage):&(im->alt.ximage); + } + dst = (format == ASA_MaskXImage )? &(im->alt.mask_ximage):&(im->alt.ximage); if( *dst == NULL ) { int depth = 0 ; @@ -151,8 +141,10 @@ Bool create_image_xim( ASVisual *asv, ASImage *im, ASAltImFormats format ) Bool create_image_argb32( ASVisual *asv, ASImage *im, ASAltImFormats format ) { - if( im->alt.argb32 == NULL ) - im->alt.argb32 = safemalloc( im->width*im->height*sizeof(ARGB32) ); + (void)asv; + (void)format; // silence unused variable warning + if (im->alt.argb32 == NULL) + im->alt.argb32 = safemalloc( im->width*im->height*sizeof(ARGB32) ); return True; } @@ -161,8 +153,9 @@ Bool create_image_argb32( ASVisual *asv, ASImage *im, ASAltImFormats format ) static void asimage_dup_line (ASImage * im, ColorPart color, unsigned int y1, unsigned int y2, unsigned int length) { - ASStorageID *part = im->channels[color]; - if (part[y2] != 0) + (void)length; // silence unused variable warning + ASStorageID *part = im->channels[color]; + if (part[y2] != 0) { forget_data(NULL, part[y2]); part[y2] = 0 ; @@ -203,6 +196,7 @@ asimage_erase_line( ASImage * im, ColorPart color, unsigned int y ) void copy_component( register CARD32 *src, register CARD32 *dst, int *unused, int len ) { + (void)unused; // silence unused variable warning #if 1 #ifdef CARD64 CARD64 *dsrc = (CARD64*)src; @@ -622,27 +616,27 @@ best_output_filter( register CARD32 *line1, register CARD32 *line2, int unused, {/* we carry half of the quantization error onto the surrounding pixels : */ /* X 7/16 */ /* 3/16 5/16 1/16 */ - register int i ; - register CARD32 errp = 0, err = 0, c; - c = line1[0]; - if( (c&0xFFFF0000)!= 0 ) - c = ( c&0x7F000000 )?0:0x0000FFFF; - errp = c&QUANT_ERR_MASK; - line1[0] = c>>QUANT_ERR_BITS ; - line2[0] += (errp*5)>>4 ; - - for( i = 1 ; i < len ; ++i ) - { - c = line1[i]; - if( (c&0xFFFF0000)!= 0 ) - c = (c&0x7F000000)?0:0x0000FFFF; - c += ((errp*7)>>4) ; - err = c&QUANT_ERR_MASK; - line1[i] = (c&0x7FFF0000)?0x000000FF:(c>>QUANT_ERR_BITS); - line2[i-1] += (err*3)>>4 ; - line2[i] += ((err*5)>>4)+(errp>>4); - errp = err ; - } + (void)unused; // silence unused variable warning + register int i; + register CARD32 errp = 0, err = 0, c; + c = line1[0]; + if ((c & 0xFFFF0000) != 0) + c = (c & 0x7F000000) ? 0 : 0x0000FFFF; + errp = c & QUANT_ERR_MASK; + line1[0] = c >> QUANT_ERR_BITS; + line2[0] += (errp * 5) >> 4; + + for (i = 1; i < len; ++i) { + c = line1[i]; + if ((c & 0xFFFF0000) != 0) + c = (c & 0x7F000000) ? 0 : 0x0000FFFF; + c += ((errp * 7) >> 4); + err = c & QUANT_ERR_MASK; + line1[i] = (c & 0x7FFF0000) ? 0x000000FF : (c >> QUANT_ERR_BITS); + line2[i - 1] += (err * 3) >> 4; + line2[i] += ((err * 5) >> 4) + (errp >> 4); + errp = err; + } } static inline void @@ -730,8 +724,9 @@ fast_output_filter( register CARD32 *src, register CARD32 *dst, short ratio, int static inline void fine_output_filter_mod( register CARD32 *data, int unused, int len ) {/* we carry half of the quantization error onto the following pixel : */ - register int i ; - register CARD32 err = 0, c; + (void)unused; // silence unused variable warning + register int i; + register CARD32 err = 0, c; for( i = 0 ; i < len ; ++i ) { c = data[i]; @@ -911,6 +906,8 @@ decode_asscanline_ximage( ASImageDecoder *imdec, unsigned int skip, int y ) { while(--x >= 0 ) dst[x] = (XGetPixel(xim, x, y) == 0)?0x00:0xFF; } +#else + (void)y; // silence unused variable warning #endif } count = MIN(width,xim_width); @@ -1140,15 +1137,15 @@ decode_image_scanline_beveled( ASImageDecoder *imdec ) int alt_right = (line*bevel->right_outline/bevel->bottom_outline)+1 ; alt_left += MAX(imdec->bevel_left-(int)bevel->left_outline,0) ; - offset_shade = MIN(alt_left, (int)scl->width ); if( (int)scl->width < imdec->bevel_right ) alt_right -= imdec->bevel_right-(int)scl->width ; -/* fprintf( stderr, __FUNCTION__ " %d: y_out = %d, alt_left = %d, offset_shade = %d, alt_right = %d, scl->width = %d, out_width = %d\n", - __LINE__, y_out, alt_left, offset_shade, alt_right, scl->width, imdec->out_width ); - */ - set_flags( scl->flags, imdec->filter ); + /* offset_shade = MIN(alt_left, (int)scl->width ); fprintf( stderr, __FUNCTION__ " %d: y_out = %d, alt_left = + %d, offset_shade = %d, alt_right = %d, scl->width = %d, out_width = %d\n", + __LINE__, y_out, alt_left, offset_shade, alt_right, scl->width, imdec->out_width ); + */ + set_flags( scl->flags, imdec->filter ); draw_solid_bevel_line( scl, alt_left, alt_left, alt_left, alt_right, bevel->hi_color, bevel->lo_color, bevel->hilo_color, bevel->lolo_color ); @@ -1247,6 +1244,7 @@ decode_image_scanline_beveled( ASImageDecoder *imdec ) ++(imdec->next_line); } +#ifndef X_DISPLAY_MISSING /* *********************************************************************/ /* ENCODER : */ inline static void @@ -1263,6 +1261,7 @@ tile_ximage_line( XImage *xim, unsigned int line, int step, int range ) dst_line += xim_step ; } } +#endif void encode_image_scanline_mask_xim( ASImageOutput *imout, ASScanline *to_store ) @@ -1294,6 +1293,9 @@ encode_image_scanline_mask_xim( ASImageOutput *imout, ASScanline *to_store ) (imout->tiling_range ? imout->tiling_range:imout->im->height) ); imout->next_line += imout->bottom_to_top; } +#else + (void)imout; + (void)to_store; // silence unused variable warning #endif } @@ -1352,6 +1354,9 @@ encode_image_scanline_xim( ASImageOutput *imout, ASScanline *to_store ) #endif imout->next_line += imout->bottom_to_top; } +#else + (void)imout; + (void)to_store; // silence unused variable warning #endif } diff --git a/graf2d/asimage/src/libAfterImage/import.c b/graf2d/asimage/src/libAfterImage/import.c index 2b422d011835c..2156a9398ae50 100644 --- a/graf2d/asimage/src/libAfterImage/import.c +++ b/graf2d/asimage/src/libAfterImage/import.c @@ -27,12 +27,6 @@ #undef DO_CLOCKING #undef DEBUG_TRANSP_GIF -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #ifdef HAVE_PNG /* Include file for users of png library. */ #include @@ -79,11 +73,7 @@ #ifdef const #undef const #endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #ifdef HAVE_GIF # include #endif @@ -310,13 +300,14 @@ void init_asimage_import_params( ASImageImportParams *iparams ) ASImage * file2ASImage( const char *file, ASFlagType what, double gamma, unsigned int compression, ... ) { - int i ; - char *paths[MAX_SEARCH_PATHS+1] ; - ASImageImportParams iparams ; - va_list ap; + (void)what; // silence unused variable warning + int i; + char *paths[MAX_SEARCH_PATHS + 1]; + ASImageImportParams iparams; + va_list ap; - init_asimage_import_params( &iparams ); - iparams.gamma = gamma ; + init_asimage_import_params(&iparams); + iparams.gamma = gamma ; iparams.compression = compression ; iparams.search_path = &(paths[0]); #if 0 @@ -373,6 +364,11 @@ file2pixmap(ASVisual *asv, Window root, const char *realfilename, Pixmap *mask_o XFreePixmap( asv->dpy, *mask_out ); *mask_out = mask ; } +#else + (void)asv; + (void)root; + (void)realfilename; + (void)mask_out; // silence unused variable warning #endif return trg ; } @@ -415,19 +411,20 @@ get_asimage_file_type( ASImageManager* imageman, const char *file ) ASImage * get_asimage( ASImageManager* imageman, const char *file, ASFlagType what, unsigned int compression ) { - ASImage *im = NULL ; - if( imageman && file ) - if( (im = fetch_asimage(imageman, file )) == NULL ) - { - im = load_image_from_path( file, &(imageman->search_path[0]), imageman->gamma); - if( im ) + (void)what; + (void)compression; // silence unused variable warning + + ASImage *im = NULL; + if (imageman && file) + if ((im = fetch_asimage(imageman, file)) == NULL) { + im = load_image_from_path(file, &(imageman->search_path[0]), imageman->gamma); + if( im ) { store_asimage( imageman, im, file ); set_flags( im->flags, ASIM_NAME_IS_FILENAME ); } - - } - return im; + } + return im; } void @@ -588,6 +585,8 @@ reload_asimage_manager( ASImageManager *imman ) return True; } } +#else + (void)imman; // silence unused variable warning #endif return False; } @@ -748,29 +747,27 @@ direntry2ASImageListEntry( const char *fname, const char *fullname, else tile_height = data->preview_height ; } - if( scale_width != im->width || scale_height != im->height ) - { - ASImage *tmp = scale_asimage( data->asv, im, scale_width, scale_height, ASA_ASImage, data->preview_compression, ASIMAGE_QUALITY_DEFAULT ); - if( tmp != NULL ) - { - destroy_asimage( &im ); - im = tmp ; - } - } - if( tile_width != im->width || tile_height != im->height ) - { - ASImage *tmp = tile_asimage( data->asv, im, 0, 0, tile_width, tile_height, TINT_NONE, ASA_ASImage, data->preview_compression, ASIMAGE_QUALITY_DEFAULT ); - if( tmp != NULL ) - { - destroy_asimage( &im ); - im = tmp ; - } - } - } - - curr->preview = im ; - } - return True; + if (scale_width != (int)im->width || scale_height != (int)im->height) { + ASImage *tmp = scale_asimage(data->asv, im, scale_width, scale_height, ASA_ASImage, + data->preview_compression, ASIMAGE_QUALITY_DEFAULT); + if (tmp != NULL) { + destroy_asimage(&im); + im = tmp; + } + } + if (tile_width != (int)im->width || tile_height != (int)im->height) { + ASImage *tmp = tile_asimage(data->asv, im, 0, 0, tile_width, tile_height, TINT_NONE, ASA_ASImage, + data->preview_compression, ASIMAGE_QUALITY_DEFAULT); + if (tmp != NULL) { + destroy_asimage(&im); + im = tmp; + } + } + } + + curr->preview = im; + } + return True; } #endif @@ -782,7 +779,8 @@ get_asimage_list( ASVisual *asv, const char *dir, unsigned int *count_ret, int (*select) (const char *) ) { - ASImageListEntry *im_list = NULL ; + (void)gamma; // silence unused variable warning + ASImageListEntry *im_list = NULL; #ifndef _WIN32 struct ASImageListAuxData aux_data ; int count ; @@ -1363,31 +1361,29 @@ png2ASImage_int( void *data, png_rw_ptr read_fn, ASImageImportParams *params ) { int i, pixel_i = -1; static CARD8 gray2bit_translation[4] = {0,85,170,255}; - for ( i = 0 ; i < row_bytes ; ++i ) - { - CARD8 b = row_pointers[y][i]; - upscaled_gray[++pixel_i] = gray2bit_translation[b&0x03]; - upscaled_gray[++pixel_i] = gray2bit_translation[(b&0xC)>>2]; - upscaled_gray[++pixel_i] = gray2bit_translation[(b&0x30)>>4]; - upscaled_gray[++pixel_i] = gray2bit_translation[(b&0xC0)>>6]; - } - im->channels[IC_RED][y] = store_data( NULL, upscaled_gray, width, rgb_flags, 0); - }else if ( bit_depth == 4 ) - { - int i, pixel_i = -1; - static CARD8 gray4bit_translation[16] = {0,17,34,51, 68,85,102,119, 136,153,170,187, 204,221,238,255}; - for ( i = 0 ; i < row_bytes ; ++i ) - { - CARD8 b = row_pointers[y][i]; - upscaled_gray[++pixel_i] = gray4bit_translation[b&0x0F]; - upscaled_gray[++pixel_i] = gray4bit_translation[(b&0xF0)>>4]; - } - im->channels[IC_RED][y] = store_data( NULL, upscaled_gray, width, rgb_flags, 0); - }else - im->channels[IC_RED][y] = store_data( NULL, row_pointers[y], row_bytes, rgb_flags, 1); - } - - if( grayscale ) + for (i = 0; (size_t)i < row_bytes; ++i) { + CARD8 b = row_pointers[y][i]; + upscaled_gray[++pixel_i] = gray2bit_translation[b & 0x03]; + upscaled_gray[++pixel_i] = gray2bit_translation[(b & 0xC) >> 2]; + upscaled_gray[++pixel_i] = gray2bit_translation[(b & 0x30) >> 4]; + upscaled_gray[++pixel_i] = gray2bit_translation[(b&0xC0)>>6]; + } + im->channels[IC_RED][y] = store_data(NULL, upscaled_gray, width, rgb_flags, 0); + } else if (bit_depth == 4) { + int i, pixel_i = -1; + static CARD8 gray4bit_translation[16] = {0, 17, 34, 51, 68, 85, 102, 119, + 136, 153, 170, 187, 204, 221, 238, 255}; + for (i = 0; (size_t)i < row_bytes; ++i) { + CARD8 b = row_pointers[y][i]; + upscaled_gray[++pixel_i] = gray4bit_translation[b & 0x0F]; + upscaled_gray[++pixel_i] = gray4bit_translation[(b & 0xF0) >> 4]; + } + im->channels[IC_RED][y] = store_data(NULL, upscaled_gray, width, rgb_flags, 0); + } else + im->channels[IC_RED][y] = store_data(NULL, row_pointers[y], row_bytes, rgb_flags, 1); + } + + if( grayscale ) { im->channels[IC_GREEN][y] = dup_data( NULL, im->channels[IC_RED][y] ); im->channels[IC_BLUE][y] = dup_data( NULL, im->channels[IC_RED][y] ); @@ -1731,11 +1727,12 @@ jpeg2ASImage( const char * path, ASImageImportParams *params ) ASImage * xcf2ASImage( const char * path, ASImageImportParams *params ) { - ASImage *im = NULL ; - /* More stuff */ - FILE *infile; /* source file */ - XcfImage *xcf_im; - START_TIME(started); + (void)params; // silence unused variable warning + ASImage *im = NULL; + /* More stuff */ + FILE *infile; /* source file */ + XcfImage *xcf_im; + START_TIME(started); /* we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. @@ -1993,26 +1990,24 @@ gif2ASImage( const char * path, ASImageImportParams *params ) { unsigned int x ; Bool do_alpha = False ; - image_y = interlaced ? gif_interlaced2y(y, height):y; - for (x = 0; x < width; ++x) - { - int c = row_pointer[x]; - if ( c == transparent) - { - c = bg_color ; - do_alpha = True ; + image_y = interlaced ? gif_interlaced2y(y, height) : (int)y; + for (x = 0; x < width; ++x) { + int c = row_pointer[x]; + if (c == transparent) { + c = bg_color; + do_alpha = True ; a[x] = 0 ; - }else - a[x] = 0x00FF ; + } else + a[x] = 0x00FF; - r[x] = cmap->Colors[c].Red; + r[x] = cmap->Colors[c].Red; g[x] = cmap->Colors[c].Green; b[x] = cmap->Colors[c].Blue; - } - row_pointer += x ; - im->channels[IC_RED][image_y] = store_data( NULL, r, width, ASStorage_RLEDiffCompress, 0); - im->channels[IC_GREEN][image_y] = store_data( NULL, g, width, ASStorage_RLEDiffCompress, 0); - im->channels[IC_BLUE][image_y] = store_data( NULL, b, width, ASStorage_RLEDiffCompress, 0); + } + row_pointer += x; + im->channels[IC_RED][image_y] = store_data(NULL, r, width, ASStorage_RLEDiffCompress, 0); + im->channels[IC_GREEN][image_y] = store_data(NULL, g, width, ASStorage_RLEDiffCompress, 0); + im->channels[IC_BLUE][image_y] = store_data( NULL, b, width, ASStorage_RLEDiffCompress, 0); if( do_alpha ) im->channels[IC_ALPHA][image_y] = store_data( NULL, a, im->width, ASStorage_RLEDiffCompress|ASStorage_Bitmap, 0); } @@ -2172,54 +2167,52 @@ tiff2ASImage( const char * path, ASImageImportParams *params ) if ( 1/* striped image */) { int strip_no; - uint32* bc; - TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc); + uint32_t *bc; + TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc); int all_strip_size = 0; - for (strip_no = 0; strip_no < TIFFNumberOfStrips(tif); ++strip_no) - all_strip_size += bc[strip_no]; - /* create one large buffer for the image data : */ - if (data_size < all_strip_size) - { - data_size = all_strip_size; + for (strip_no = 0; strip_no < (int)TIFFNumberOfStrips(tif); ++strip_no) + all_strip_size += bc[strip_no]; + /* create one large buffer for the image data : */ + if (data_size < all_strip_size) { + data_size = all_strip_size; _TIFFfree(data); data = _TIFFmalloc(data_size); - } + } - if (planar_config == PLANARCONFIG_CONTIG) + if (planar_config == PLANARCONFIG_CONTIG) { - for (strip_no = 0; strip_no < TIFFNumberOfStrips(tif); strip_no++) - { - int bytes_in; - if (bits == 12) /* can't use libTIFF's function - it can't handle 12bit data ! */ - { - /* PENTAX cameras claim that data is compressed as runlength packbits - - it is not in fact run-length, which confuses libTIFF - */ - bytes_in = TIFFReadRawStrip(tif, strip_no, data+loaded_data_size, data_size-loaded_data_size); - }else - bytes_in = TIFFReadEncodedStrip(tif, strip_no, data+loaded_data_size, data_size-loaded_data_size); - -LOCAL_DEBUG_OUT( "strip size = %d, bytes_in = %d, bytes_per_row = %d", bc[strip_no], bytes_in, bytes_per_row); - if (bytes_in >= 0) + for (strip_no = 0; strip_no < (int)TIFFNumberOfStrips(tif); strip_no++) { + int bytes_in; + if (bits == 12) /* can't use libTIFF's function - it can't handle 12bit data ! */ + { + /* PENTAX cameras claim that data is compressed as runlength packbits - + it is not in fact run-length, which confuses libTIFF + */ + bytes_in = + TIFFReadRawStrip(tif, strip_no, data + loaded_data_size, data_size - loaded_data_size); + } else + bytes_in = TIFFReadEncodedStrip(tif, strip_no, data + loaded_data_size, + data_size - loaded_data_size); + + LOCAL_DEBUG_OUT("strip size = %d, bytes_in = %d, bytes_per_row = %d", bc[strip_no], bytes_in, + bytes_per_row); + if (bytes_in >= 0) loaded_data_size += bytes_in; else { LOCAL_DEBUG_OUT( "failed reading strip %d", strip_no); } - } - } else if (planar_config == PLANARCONFIG_SEPARATE) - { - /* TODO: do something with split channels */ - } - }else - { - /* TODO: implement support for tiled images */ - } - - if (loaded_data_size > 0) - { - int offset; - int data_row = 0; + } + } else if (planar_config == PLANARCONFIG_SEPARATE) { + /* TODO: do something with split channels */ + } + } else { + /* TODO: implement support for tiled images */ + } + + if (loaded_data_size > 0) { + int offset; + int data_row = 0; do { offset = data_row * bytes_per_row; @@ -2252,9 +2245,9 @@ LOCAL_DEBUG_OUT( "strip size = %d, bytes_in = %d, bytes_per_row = %d", bc[strip_ data_row += loaded_rows; }while (offset < loaded_data_size); success = True; - } - } - destroy_asim_strip (&strip); + } + } + destroy_asim_strip (&strip); stop_image_output( &imout ); if (!success) @@ -2266,51 +2259,48 @@ LOCAL_DEBUG_OUT( "strip size = %d, bytes_in = %d, bytes_per_row = %d", bc[strip_ { register CARD32 *row = data ; int y = first_row + rows_per_strip ; - if( y > height ) - y = height ; - while( --y >= first_row ) - { - int x ; - for( x = 0 ; x < width ; ++x ) - { - CARD32 c = row[x] ; - if( depth == 4 || depth == 2 ) - a[x] = TIFFGetA(c); - r[x] = TIFFGetR(c); - if( depth > 2 ) + if (y > (int)height) + y = height; + while (--y >= first_row) { + int x; + for (x = 0; x < (int)width; ++x) { + CARD32 c = row[x]; + if (depth == 4 || depth == 2) + a[x] = TIFFGetA(c); + r[x] = TIFFGetR(c); + if( depth > 2 ) { g[x] = TIFFGetG(c); b[x] = TIFFGetB(c); } - } - im->channels[IC_RED][y] = store_data( NULL, r, width, store_flags, 0); - if( depth > 2 ) - { - im->channels[IC_GREEN][y] = store_data( NULL, g, width, store_flags, 0); - im->channels[IC_BLUE][y] = store_data( NULL, b, width, store_flags, 0); - }else - { - im->channels[IC_GREEN][y] = dup_data( NULL, im->channels[IC_RED][y]); - im->channels[IC_BLUE][y] = dup_data( NULL, im->channels[IC_RED][y]); - } - - if( depth == 4 || depth == 2 ) - im->channels[IC_ALPHA][y] = store_data( NULL, a, width, store_flags, 0); - row += width ; - } - /* move onto the next strip now : */ - do - { - first_row += rows_per_strip ; - }while (first_row < height && !TIFFReadRGBAStrip(tif, first_row, (void*)data)); - - }while (first_row < height); - } - set_asstorage_block_size( NULL, old_storage_block_size ); - - if( b ) free( b ); - if( g ) free( g ); - if( r ) free( r ); + } + im->channels[IC_RED][y] = store_data(NULL, r, width, store_flags, 0); + if (depth > 2) { + im->channels[IC_GREEN][y] = store_data(NULL, g, width, store_flags, 0); + im->channels[IC_BLUE][y] = store_data(NULL, b, width, store_flags, 0); + } else { + im->channels[IC_GREEN][y] = dup_data(NULL, im->channels[IC_RED][y]); + im->channels[IC_BLUE][y] = dup_data(NULL, im->channels[IC_RED][y]); + } + + if (depth == 4 || depth == 2) + im->channels[IC_ALPHA][y] = store_data(NULL, a, width, store_flags, 0); + row += width ; + } + /* move onto the next strip now : */ + do { + first_row += rows_per_strip ; + } while (first_row < (int)height && !TIFFReadRGBAStrip(tif, first_row, (void *)data)); + + } while (first_row < (int)height); + } + set_asstorage_block_size(NULL, old_storage_block_size); + + if (b) + free(b); + if (g) + free(g); + if( r ) free( r ); if( a ) free( a ); _TIFFfree(data); } @@ -2327,6 +2317,7 @@ ASImage * tiff2ASImage( const char * path, ASImageImportParams *params ) { show_error( "unable to load file \"%s\" - missing TIFF image format libraries.\n", path ); + (void)params; // silence unused variable warning return NULL ; } #endif /* TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF TIFF */ @@ -2335,6 +2326,11 @@ tiff2ASImage( const char * path, ASImageImportParams *params ) static ASImage * load_xml2ASImage( ASImageManager *imman, const char *path, unsigned int compression, int width, int height ) { + (void)imman; + (void)path; + (void)compression; + (void)width; + (void)height; // silence unused variable warning // Incompatible license fprintf(stderr, "ERROR in load_xml2ASImage: XML import is disabled.\n"); ASImage *im = NULL ; @@ -2459,8 +2455,9 @@ svg2ASImage( const char * path, ASImageImportParams *params ) ASImage * svg2ASImage( const char * path, ASImageImportParams *params ) { - show_error( "unable to load file \"%s\" - missing SVG image format libraries.\n", path ); - return NULL ; + (void)params; // silence unused variable warning + show_error("unable to load file \"%s\" - missing SVG image format libraries.\n", path); + return NULL; } #endif /* SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG SVG */ @@ -2517,15 +2514,21 @@ typedef struct ASTGAImageData static Bool load_tga_colormapped(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table ) { - - return True; + (void)infile; + (void)tga; + (void)cmap; + (void)buf; + (void)read_buf; + (void)gamma_table; // silence unused variable warning + return True; } static Bool load_tga_truecolor(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table ) { - CARD32 *a = buf->alpha ; - CARD32 *r = buf->red ; - CARD32 *g = buf->green ; + (void)cmap; // silence unused variable warning + CARD32 *a = buf->alpha; + CARD32 *r = buf->red; + CARD32 *g = buf->green ; CARD32 *b = buf->blue ; int bpp = (tga->ImageSpec.Depth+7)/8; int bpl = buf->width*bpp; @@ -2567,26 +2570,46 @@ static Bool load_tga_truecolor(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cm static Bool load_tga_bw(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table ) { - - return True; + (void)infile; + (void)tga; + (void)cmap; + (void)buf; + (void)read_buf; + (void)gamma_table; // silence unused variable warning + return True; } static Bool load_tga_rle_colormapped(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table ) { - - return True; + (void)infile; + (void)tga; + (void)cmap; + (void)buf; + (void)read_buf; + (void)gamma_table; // silence unused variable warning + return True; } static Bool load_tga_rle_truecolor(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table ) { - - return True; + (void)infile; + (void)tga; + (void)cmap; + (void)buf; + (void)read_buf; + (void)gamma_table; // silence unused variable warning + return True; } static Bool load_tga_rle_bw(FILE *infile, ASTGAHeader *tga, ASTGAColorMap *cmap, ASScanline *buf, CARD8 *read_buf, CARD8 *gamma_table ) { - - return True; + (void)infile; + (void)tga; + (void)cmap; + (void)buf; + (void)read_buf; + (void)gamma_table; // silence unused variable warning + return True; } @@ -2694,7 +2717,9 @@ tga2ASImage( const char * path, ASImageImportParams *params ) ASImage * convert_argb2ASImage( ASVisual *asv, int width, int height, ARGB32 *argb, CARD8 *gamma_table ) { - ASImage *im = NULL ; + (void)asv; + (void)gamma_table; // silence unused variable warning + ASImage *im = NULL ; ASImageOutput *imout ; im = create_asimage( width, height, 100 ); if((imout = start_image_output( NULL, im, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT)) == NULL ) diff --git a/graf2d/asimage/src/libAfterImage/import.h b/graf2d/asimage/src/libAfterImage/import.h index 23980e5457fd9..0060fd4947633 100644 --- a/graf2d/asimage/src/libAfterImage/import.h +++ b/graf2d/asimage/src/libAfterImage/import.h @@ -186,8 +186,6 @@ ASImage *argb2ASImage( const char *path, ASImageImportParams *params ); * files. * After the file is found file2ASImage() attempts to detect file format, * and if it is known it will load it into new ASImage structure. - * EXAMPLE - * asview.c: ASView.2 *********/ /****f* libAfterImage/import/get_asimage() * NAME diff --git a/graf2d/asimage/src/libAfterImage/install-sh b/graf2d/asimage/src/libAfterImage/install-sh deleted file mode 100755 index 6ebe46de6cf49..0000000000000 --- a/graf2d/asimage/src/libAfterImage/install-sh +++ /dev/null @@ -1,323 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2004-12-17.09 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# 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 -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -chmodcmd="$chmodprog 0755" -chowncmd= -chgrpcmd= -stripcmd= -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src= -dst= -dir_arg= -dstarg= -no_target_directory= - -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: --c (ignored) --d create directories instead of installing files. --g GROUP $chgrpprog installed files to GROUP. --m MODE $chmodprog installed files to MODE. --o USER $chownprog installed files to USER. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG -" - -while test -n "$1"; do - case $1 in - -c) shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - --help) echo "$usage"; exit 0;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t) dstarg=$2 - shift - shift - continue;; - - -T) no_target_directory=true - shift - continue;; - - --version) echo "$0 $scriptversion"; exit 0;; - - *) # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - test -n "$dir_arg$dstarg" && break - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done - break;; - esac -done - -if test -z "$1"; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src ;; - esac - - if test -n "$dir_arg"; then - dst=$src - src= - - if test -d "$dst"; then - mkdircmd=: - chmodcmd= - else - mkdircmd=$mkdirprog - fi - else - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dstarg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 - fi - dst=$dst/`basename "$src"` - fi - fi - - # This sed command emulates the dirname command. - dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` - - # Make sure that the destination directory exists. - - # Skip lots of stat calls in the usual case. - if test ! -d "$dstdir"; then - defaultIFS=' - ' - IFS="${IFS-$defaultIFS}" - - oIFS=$IFS - # Some sh's can't handle IFS=/ for some reason. - IFS='%' - set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` - shift - IFS=$oIFS - - pathcomp= - - while test $# -ne 0 ; do - pathcomp=$pathcomp$1 - shift - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # mkdir can fail with a `File exist' error in case several - # install-sh are creating the directory concurrently. This - # is OK. - test -d "$pathcomp" || exit - fi - pathcomp=$pathcomp/ - done - fi - - if test -n "$dir_arg"; then - $doit $mkdircmd "$dst" \ - && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } - - else - dstfile=`basename "$dst"` - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - trap '(exit $?); exit' 1 2 13 15 - - # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dstdir/$dstfile"; then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ - || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ - || { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit 1 - } - else - : - fi - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - } - } - fi || { (exit 1); exit 1; } -done - -# The final little trick to "correctly" pass the exit status to the exit trap. -{ - (exit 0); exit 0 -} - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/graf2d/asimage/src/libAfterImage/libAfterImage.dsp b/graf2d/asimage/src/libAfterImage/libAfterImage.dsp deleted file mode 100644 index 9f24ff975ddb8..0000000000000 --- a/graf2d/asimage/src/libAfterImage/libAfterImage.dsp +++ /dev/null @@ -1,573 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libAfterImage" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=libAfterImage - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libAfterImage.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libAfterImage.mak" CFG="libAfterImage - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libAfterImage - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libAfterImage - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libAfterImage - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NO_DEBUG_OUTPUT" /D "NDEBUG" /D "_LIB" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"libAfterImage.lib" - -!ELSEIF "$(CFG)" == "libAfterImage - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "win32\Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "libAfterImage - Win32 Release" -# Name "libAfterImage - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Group "PNG Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\libpng\png.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngerror.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngget.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngmem.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngpread.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngread.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngrio.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngrtran.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngrutil.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngset.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngtrans.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngwio.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngwrite.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngwtran.c -# End Source File -# Begin Source File - -SOURCE=.\libpng\pngwutil.c -# End Source File -# End Group -# Begin Group "JPG Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\libjpeg\jcapimin.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcapistd.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jccoefct.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jccolor.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcdctmgr.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jchuff.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcinit.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcmainct.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcmarker.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcmaster.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcomapi.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcparam.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcphuff.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcprepct.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcsample.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jctrans.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdapimin.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdapistd.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdatadst.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdatasrc.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdcoefct.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdcolor.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\transupp.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jaricom.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdarith.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jcarith.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jddctmgr.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdhuff.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdinput.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdmainct.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdmarker.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdmaster.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdmerge.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdpostct.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdsample.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jdtrans.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jerror.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jfdctflt.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jfdctfst.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jfdctint.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jidctflt.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jidctfst.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jidctint.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jmemmgr.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jmemnobs.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jquant1.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jquant2.c -# End Source File -# Begin Source File - -SOURCE=.\libjpeg\jutils.c -# End Source File -# End Group -# Begin Group "ZLIB Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\zlib\adler32.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\compress.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\crc32.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\deflate.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\gzio.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\infback.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\inffast.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\inflate.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\inftrees.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\trees.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\uncompr.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\zutil.c -# End Source File -# End Group -# Begin Group "UNGIF Files" - -# PROP Default_Filter "*.c" -# Begin Source File - -SOURCE=.\libungif\dgif_lib.c -# End Source File -# Begin Source File - -SOURCE=.\libungif\egif_lib.c -# End Source File -# Begin Source File - -SOURCE=.\libungif\gif_err.c -# End Source File -# Begin Source File - -SOURCE=.\libungif\gifalloc.c -# End Source File -# End Group -# Begin Source File - -SOURCE=.\afterbase.c -# End Source File -# Begin Source File - -SOURCE=.\ascmap.c -# End Source File -# Begin Source File - -SOURCE=.\asfont.c -# End Source File -# Begin Source File - -SOURCE=.\asimage.c -# End Source File -# Begin Source File - -SOURCE=.\asstorage.c -# End Source File -# Begin Source File - -SOURCE=.\asvisual.c -# End Source File -# Begin Source File - -SOURCE=.\blender.c -# End Source File -# Begin Source File - -SOURCE=.\bmp.c -# End Source File -# Begin Source File - -SOURCE=.\char2uni.c -# End Source File -# Begin Source File - -SOURCE=.\export.c -# End Source File -# Begin Source File - -SOURCE=.\imencdec.c -# End Source File -# Begin Source File - -SOURCE=.\import.c -# End Source File -# Begin Source File - -SOURCE=.\transform.c -# End Source File -# Begin Source File - -SOURCE=.\ungif.c -# End Source File -# Begin Source File - -SOURCE=.\xcf.c -# End Source File -# Begin Source File - -SOURCE=.\ximage.c -# End Source File -# Begin Source File - -SOURCE=.\xpm.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\win32\afterbase.h -# End Source File -# Begin Source File - -SOURCE=.\afterimage.h -# End Source File -# Begin Source File - -SOURCE=.\ascmap.h -# End Source File -# Begin Source File - -SOURCE=.\asfont.h -# End Source File -# Begin Source File - -SOURCE=.\asim_afterbase.h -# End Source File -# Begin Source File - -SOURCE=.\asimage.h -# End Source File -# Begin Source File - -SOURCE=.\asvisual.h -# End Source File -# Begin Source File - -SOURCE=.\blender.h -# End Source File -# Begin Source File - -SOURCE=.\bmp.h -# End Source File -# Begin Source File - -SOURCE=.\char2uni.h -# End Source File -# Begin Source File - -SOURCE=.\win32\config.h -# End Source File -# Begin Source File - -SOURCE=.\export.h -# End Source File -# Begin Source File - -SOURCE=.\imencdec.h -# End Source File -# Begin Source File - -SOURCE=.\import.h -# End Source File -# Begin Source File - -SOURCE=.\transform.h -# End Source File -# Begin Source File - -SOURCE=.\ungif.h -# End Source File -# Begin Source File - -SOURCE=.\xcf.h -# End Source File -# Begin Source File - -SOURCE=.\ximage.h -# End Source File -# Begin Source File - -SOURCE=.\xpm.h -# End Source File -# Begin Source File - -SOURCE=.\xwrap.h -# End Source File -# End Group -# End Target -# End Project diff --git a/graf2d/asimage/src/libAfterImage/libAfterImage.dsw b/graf2d/asimage/src/libAfterImage/libAfterImage.dsw deleted file mode 100644 index 6966f1d96786b..0000000000000 --- a/graf2d/asimage/src/libAfterImage/libAfterImage.dsw +++ /dev/null @@ -1,44 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "asview"=".\win32\asview.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libAfterImage - End Project Dependency -}}} - -############################################################################### - -Project: "libAfterImage"=".\libAfterImage.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/graf2d/asimage/src/libAfterImage/libAfterImage.mak b/graf2d/asimage/src/libAfterImage/libAfterImage.mak deleted file mode 100644 index d6844e6c4c1ed..0000000000000 --- a/graf2d/asimage/src/libAfterImage/libAfterImage.mak +++ /dev/null @@ -1,813 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Based on libAfterImage.dsp -!IF "$(CFG)" == "" -CFG=libAfterImage - Win32 Debug -!MESSAGE No configuration specified. Defaulting to libAfterImage - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "libAfterImage - Win32 Release" && "$(CFG)" != "libAfterImage - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libAfterImage.mak" CFG="libAfterImage - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libAfterImage - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libAfterImage - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libAfterImage - Win32 Release" - -OUTDIR=.\Release -INTDIR=.\Release - -ALL : ".\libAfterImage.lib" - - -CLEAN : - -@erase /q "$(INTDIR)" - -@erase ".\libAfterImage.lib" - -DISTCLEAN: CLEAN - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP_PROJ=$(FREETYPEDIRI) /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "NO_DEBUG_OUTPUT" /D "_MBCS" /D "_LIB" /Fp"$(INTDIR)\libAfterImage.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c $(NMAKECXXFLAGS) -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\libAfterImage.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"libAfterImage.lib" -LIB32_OBJS= \ - "$(INTDIR)\png.obj" \ - "$(INTDIR)\pngerror.obj" \ - "$(INTDIR)\pngget.obj" \ - "$(INTDIR)\pngmem.obj" \ - "$(INTDIR)\pngpread.obj" \ - "$(INTDIR)\pngread.obj" \ - "$(INTDIR)\pngrio.obj" \ - "$(INTDIR)\pngrtran.obj" \ - "$(INTDIR)\pngrutil.obj" \ - "$(INTDIR)\pngset.obj" \ - "$(INTDIR)\pngtrans.obj" \ - "$(INTDIR)\pngwio.obj" \ - "$(INTDIR)\pngwrite.obj" \ - "$(INTDIR)\pngwtran.obj" \ - "$(INTDIR)\pngwutil.obj" \ - "$(INTDIR)\jcapimin.obj" \ - "$(INTDIR)\jcapistd.obj" \ - "$(INTDIR)\jccoefct.obj" \ - "$(INTDIR)\jccolor.obj" \ - "$(INTDIR)\jcdctmgr.obj" \ - "$(INTDIR)\jchuff.obj" \ - "$(INTDIR)\jcinit.obj" \ - "$(INTDIR)\jcmainct.obj" \ - "$(INTDIR)\jcmarker.obj" \ - "$(INTDIR)\jcmaster.obj" \ - "$(INTDIR)\jcomapi.obj" \ - "$(INTDIR)\jcparam.obj" \ - "$(INTDIR)\jcphuff.obj" \ - "$(INTDIR)\jcprepct.obj" \ - "$(INTDIR)\jcsample.obj" \ - "$(INTDIR)\jctrans.obj" \ - "$(INTDIR)\jdapimin.obj" \ - "$(INTDIR)\jdapistd.obj" \ - "$(INTDIR)\jdatadst.obj" \ - "$(INTDIR)\jdatasrc.obj" \ - "$(INTDIR)\jdcoefct.obj" \ - "$(INTDIR)\jdcolor.obj" \ - "$(INTDIR)\transupp.obj" \ - "$(INTDIR)\jaricom.obj" \ - "$(INTDIR)\jdarith.obj" \ - "$(INTDIR)\jcarith.obj" \ - "$(INTDIR)\jddctmgr.obj" \ - "$(INTDIR)\jdhuff.obj" \ - "$(INTDIR)\jdinput.obj" \ - "$(INTDIR)\jdmainct.obj" \ - "$(INTDIR)\jdmarker.obj" \ - "$(INTDIR)\jdmaster.obj" \ - "$(INTDIR)\jdmerge.obj" \ - "$(INTDIR)\jdpostct.obj" \ - "$(INTDIR)\jdsample.obj" \ - "$(INTDIR)\jdtrans.obj" \ - "$(INTDIR)\jerror.obj" \ - "$(INTDIR)\jfdctflt.obj" \ - "$(INTDIR)\jfdctfst.obj" \ - "$(INTDIR)\jfdctint.obj" \ - "$(INTDIR)\jidctflt.obj" \ - "$(INTDIR)\jidctfst.obj" \ - "$(INTDIR)\jidctint.obj" \ - "$(INTDIR)\jmemmgr.obj" \ - "$(INTDIR)\jmemnobs.obj" \ - "$(INTDIR)\jquant1.obj" \ - "$(INTDIR)\jquant2.obj" \ - "$(INTDIR)\jutils.obj" \ - "$(INTDIR)\dgif_lib.obj" \ - "$(INTDIR)\egif_lib.obj" \ - "$(INTDIR)\gif_err.obj" \ - "$(INTDIR)\gifalloc.obj" \ - "$(INTDIR)\gif_hash.obj" \ - "$(INTDIR)\afterbase.obj" \ - "$(INTDIR)\ascmap.obj" \ - "$(INTDIR)\asfont.obj" \ - "$(INTDIR)\asimage.obj" \ - "$(INTDIR)\asstorage.obj" \ - "$(INTDIR)\asvisual.obj" \ - "$(INTDIR)\blender.obj" \ - "$(INTDIR)\bmp.obj" \ - "$(INTDIR)\char2uni.obj" \ - "$(INTDIR)\export.obj" \ - "$(INTDIR)\import.obj" \ - "$(INTDIR)\transform.obj" \ - "$(INTDIR)\ungif.obj" \ - "$(INTDIR)\xcf.obj" \ - "$(INTDIR)\ximage.obj" \ - "$(INTDIR)\xpm.obj" \ - "$(INTDIR)\draw.obj" \ - "$(INTDIR)\imencdec.obj" \ - "$(INTDIR)\scanline.obj" - -".\libAfterImage.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "libAfterImage - Win32 Debug" - -OUTDIR=. -INTDIR=.\win32\Debug -# Begin Custom Macros -OutDir=. -# End Custom Macros - -ALL : "$(OUTDIR)\libAfterImage.lib" - - -CLEAN : - -@erase /q "$(INTDIR)" - -@erase "$(OUTDIR)\libAfterImage.lib" - -DISTCLEAN: CLEAN - -"$(INTDIR)" : - if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" - -CPP_PROJ=$(FREETYPEDIRI) /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "NO_DEBUG_OUTPUT" /D "_MBCS" /D "_LIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c $(NMAKECXXFLAGS) -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\libAfterImage.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"$(OUTDIR)\libAfterImage.lib" -LIB32_OBJS= \ - "$(INTDIR)\png.obj" \ - "$(INTDIR)\pngerror.obj" \ - "$(INTDIR)\pngget.obj" \ - "$(INTDIR)\pngmem.obj" \ - "$(INTDIR)\pngpread.obj" \ - "$(INTDIR)\pngread.obj" \ - "$(INTDIR)\pngrio.obj" \ - "$(INTDIR)\pngrtran.obj" \ - "$(INTDIR)\pngrutil.obj" \ - "$(INTDIR)\pngset.obj" \ - "$(INTDIR)\pngtrans.obj" \ - "$(INTDIR)\pngwio.obj" \ - "$(INTDIR)\pngwrite.obj" \ - "$(INTDIR)\pngwtran.obj" \ - "$(INTDIR)\pngwutil.obj" \ - "$(INTDIR)\jcapimin.obj" \ - "$(INTDIR)\jcapistd.obj" \ - "$(INTDIR)\jccoefct.obj" \ - "$(INTDIR)\jccolor.obj" \ - "$(INTDIR)\jcdctmgr.obj" \ - "$(INTDIR)\jchuff.obj" \ - "$(INTDIR)\jcinit.obj" \ - "$(INTDIR)\jcmainct.obj" \ - "$(INTDIR)\jcmarker.obj" \ - "$(INTDIR)\jcmaster.obj" \ - "$(INTDIR)\jcomapi.obj" \ - "$(INTDIR)\jcparam.obj" \ - "$(INTDIR)\jcphuff.obj" \ - "$(INTDIR)\jcprepct.obj" \ - "$(INTDIR)\jcsample.obj" \ - "$(INTDIR)\jctrans.obj" \ - "$(INTDIR)\jdapimin.obj" \ - "$(INTDIR)\jdapistd.obj" \ - "$(INTDIR)\jdatadst.obj" \ - "$(INTDIR)\jdatasrc.obj" \ - "$(INTDIR)\jdcoefct.obj" \ - "$(INTDIR)\jdcolor.obj" \ - "$(INTDIR)\transupp.obj" \ - "$(INTDIR)\jaricom.obj" \ - "$(INTDIR)\jdarith.obj" \ - "$(INTDIR)\jcarith.obj" \ - "$(INTDIR)\jddctmgr.obj" \ - "$(INTDIR)\jdhuff.obj" \ - "$(INTDIR)\jdinput.obj" \ - "$(INTDIR)\jdmainct.obj" \ - "$(INTDIR)\jdmarker.obj" \ - "$(INTDIR)\jdmaster.obj" \ - "$(INTDIR)\jdmerge.obj" \ - "$(INTDIR)\jdpostct.obj" \ - "$(INTDIR)\jdsample.obj" \ - "$(INTDIR)\jdtrans.obj" \ - "$(INTDIR)\jerror.obj" \ - "$(INTDIR)\jfdctflt.obj" \ - "$(INTDIR)\jfdctfst.obj" \ - "$(INTDIR)\jfdctint.obj" \ - "$(INTDIR)\jidctflt.obj" \ - "$(INTDIR)\jidctfst.obj" \ - "$(INTDIR)\jidctint.obj" \ - "$(INTDIR)\jmemmgr.obj" \ - "$(INTDIR)\jmemnobs.obj" \ - "$(INTDIR)\jquant1.obj" \ - "$(INTDIR)\jquant2.obj" \ - "$(INTDIR)\jutils.obj" \ - "$(INTDIR)\dgif_lib.obj" \ - "$(INTDIR)\egif_lib.obj" \ - "$(INTDIR)\gif_err.obj" \ - "$(INTDIR)\gifalloc.obj" \ - "$(INTDIR)\gif_hash.obj" \ - "$(INTDIR)\afterbase.obj" \ - "$(INTDIR)\ascmap.obj" \ - "$(INTDIR)\asfont.obj" \ - "$(INTDIR)\asimage.obj" \ - "$(INTDIR)\asstorage.obj" \ - "$(INTDIR)\asvisual.obj" \ - "$(INTDIR)\blender.obj" \ - "$(INTDIR)\bmp.obj" \ - "$(INTDIR)\char2uni.obj" \ - "$(INTDIR)\export.obj" \ - "$(INTDIR)\import.obj" \ - "$(INTDIR)\transform.obj" \ - "$(INTDIR)\ungif.obj" \ - "$(INTDIR)\xcf.obj" \ - "$(INTDIR)\ximage.obj" \ - "$(INTDIR)\xpm.obj" \ - "$(INTDIR)\draw.obj" \ - "$(INTDIR)\imencdec.obj" \ - "$(INTDIR)\scanline.obj" - -"$(OUTDIR)\libAfterImage.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ENDIF - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - - -!IF "$(NO_EXTERNAL_DEPS)" != "1" -!IF EXISTS("libAfterImage.dep") -!INCLUDE "libAfterImage.dep" -!ELSE -!MESSAGE Cannot find "libAfterImage.dep" -!ENDIF -!ENDIF - - -!IF "$(CFG)" == "libAfterImage - Win32 Release" || "$(CFG)" == "libAfterImage - Win32 Debug" -SOURCE=.\libpng\png.c - -"$(INTDIR)\png.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngerror.c - -"$(INTDIR)\pngerror.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngget.c - -"$(INTDIR)\pngget.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngmem.c - -"$(INTDIR)\pngmem.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngpread.c - -"$(INTDIR)\pngpread.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngread.c - -"$(INTDIR)\pngread.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngrio.c - -"$(INTDIR)\pngrio.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngrtran.c - -"$(INTDIR)\pngrtran.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngrutil.c - -"$(INTDIR)\pngrutil.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngset.c - -"$(INTDIR)\pngset.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngtrans.c - -"$(INTDIR)\pngtrans.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngwio.c - -"$(INTDIR)\pngwio.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngwrite.c - -"$(INTDIR)\pngwrite.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngwtran.c - -"$(INTDIR)\pngwtran.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libpng\pngwutil.c - -"$(INTDIR)\pngwutil.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcapimin.c - -"$(INTDIR)\jcapimin.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcapistd.c - -"$(INTDIR)\jcapistd.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jccoefct.c - -"$(INTDIR)\jccoefct.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jccolor.c - -"$(INTDIR)\jccolor.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcdctmgr.c - -"$(INTDIR)\jcdctmgr.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jchuff.c - -"$(INTDIR)\jchuff.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcinit.c - -"$(INTDIR)\jcinit.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcmainct.c - -"$(INTDIR)\jcmainct.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcmarker.c - -"$(INTDIR)\jcmarker.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcmaster.c - -"$(INTDIR)\jcmaster.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcomapi.c - -"$(INTDIR)\jcomapi.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcparam.c - -"$(INTDIR)\jcparam.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcphuff.c - -"$(INTDIR)\jcphuff.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcprepct.c - -"$(INTDIR)\jcprepct.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcsample.c - -"$(INTDIR)\jcsample.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jctrans.c - -"$(INTDIR)\jctrans.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdapimin.c - -"$(INTDIR)\jdapimin.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdapistd.c - -"$(INTDIR)\jdapistd.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdatadst.c - -"$(INTDIR)\jdatadst.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdatasrc.c - -"$(INTDIR)\jdatasrc.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdcoefct.c - -"$(INTDIR)\jdcoefct.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdcolor.c - -"$(INTDIR)\jdcolor.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\transupp.c - -"$(INTDIR)\transupp.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jaricom.c - -"$(INTDIR)\jaricom.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdarith.c - -"$(INTDIR)\jdarith.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jcarith.c - -"$(INTDIR)\jcarith.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jddctmgr.c - -"$(INTDIR)\jddctmgr.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdhuff.c - -"$(INTDIR)\jdhuff.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdinput.c - -"$(INTDIR)\jdinput.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdmainct.c - -"$(INTDIR)\jdmainct.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdmarker.c - -"$(INTDIR)\jdmarker.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdmaster.c - -"$(INTDIR)\jdmaster.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdmerge.c - -"$(INTDIR)\jdmerge.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdpostct.c - -"$(INTDIR)\jdpostct.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdsample.c - -"$(INTDIR)\jdsample.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jdtrans.c - -"$(INTDIR)\jdtrans.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jerror.c - -"$(INTDIR)\jerror.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jfdctflt.c - -"$(INTDIR)\jfdctflt.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jfdctfst.c - -"$(INTDIR)\jfdctfst.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jfdctint.c - -"$(INTDIR)\jfdctint.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jidctflt.c - -"$(INTDIR)\jidctflt.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jidctfst.c - -"$(INTDIR)\jidctfst.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jidctint.c - -"$(INTDIR)\jidctint.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jmemmgr.c - -"$(INTDIR)\jmemmgr.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jmemnobs.c - -"$(INTDIR)\jmemnobs.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jquant1.c - -"$(INTDIR)\jquant1.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jquant2.c - -"$(INTDIR)\jquant2.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libjpeg\jutils.c - -"$(INTDIR)\jutils.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libungif\dgif_lib.c - -"$(INTDIR)\dgif_lib.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libungif\egif_lib.c - -"$(INTDIR)\egif_lib.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libungif\gif_err.c - -"$(INTDIR)\gif_err.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libungif\gifalloc.c - -"$(INTDIR)\gifalloc.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\libungif\gif_hash.c - -"$(INTDIR)\gif_hash.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=.\afterbase.c - -"$(INTDIR)\afterbase.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ascmap.c - -"$(INTDIR)\ascmap.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\asfont.c - -"$(INTDIR)\asfont.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\asimage.c - -"$(INTDIR)\asimage.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\asstorage.c - -"$(INTDIR)\asstorage.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\asvisual.c - -"$(INTDIR)\asvisual.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\blender.c - -"$(INTDIR)\blender.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\bmp.c - -"$(INTDIR)\bmp.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\char2uni.c - -"$(INTDIR)\char2uni.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\export.c - -"$(INTDIR)\export.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\imencdec.c - -"$(INTDIR)\imencdec.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\import.c - -"$(INTDIR)\import.obj" : $(SOURCE) "$(INTDIR)" - - -"$(INTDIR)\transform.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ungif.c - -"$(INTDIR)\ungif.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\xcf.c - -"$(INTDIR)\xcf.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\ximage.c - -"$(INTDIR)\ximage.obj" : $(SOURCE) "$(INTDIR)" - - -SOURCE=.\xpm.c - -"$(INTDIR)\xpm.obj" : $(SOURCE) "$(INTDIR)" - -SOURCE=.\draw.c - -"$(INTDIR)\draw.obj" : $(SOURCE) "$(INTDIR)" - -SOURCE=.\scanline.c - -"$(INTDIR)\scanline.obj" : $(SOURCE) "$(INTDIR)" - - -!ENDIF - diff --git a/graf2d/asimage/src/libAfterImage/scanline.c b/graf2d/asimage/src/libAfterImage/scanline.c index b8cbd1dde8260..add6fba000ba7 100644 --- a/graf2d/asimage/src/libAfterImage/scanline.c +++ b/graf2d/asimage/src/libAfterImage/scanline.c @@ -16,12 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #define LOCAL_DEBUG #include #ifdef HAVE_UNISTD_H @@ -33,12 +27,8 @@ #ifdef HAVE_STDARG_H #include #endif - -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif + +#include "afterbase.h" #include "scanline.h" @@ -317,8 +307,9 @@ typedef void (*ASIMDiagInterpolationFunc) (CARD32 *dst, CARD32 **channs, int wid void interpolate_channel_v_15x51 (CARD32 *dst, CARD32 **channs, int width, int offset) { - /* Assumptions : channs is array of 5 CARD32 pointers not NULL */ - int x; + (void)offset; // silence unused variable warning + /* Assumptions : channs is array of 5 CARD32 pointers not NULL */ + int x; for (x = 0; x < width; ++x) { int v = (int)channs[1][x]*5+(int)channs[3][x]*5-(int)channs[4][x]-(int)channs[0][x]; @@ -342,8 +333,9 @@ interpolate_channel_v_checkered_15x51 (CARD32 *dst, CARD32 **channs, int width, void smooth_channel_v_15x51 (CARD32 *dst, CARD32 **channs, int width, int offset) { - /* Assumptions : channs is array of 5 CARD32 pointers not NULL */ - int x; + (void)offset; // silence unused variable warning + /* Assumptions : channs is array of 5 CARD32 pointers not NULL */ + int x; for (x = 0; x < width; ++x) { int v = (int)(channs[2][x]<<3) + (int)channs[1][x]*5+(int)channs[3][x]*5-(int)channs[4][x]-(int)channs[0][x]; @@ -583,7 +575,8 @@ Bool calculate_green_diff(ASIMStrip *strip, int line, int chan, int offset) Bool interpolate_green_diff(ASIMStrip *strip, int line, int chan, int offset) { - if (line > 0 && line < strip->size-1) + (void)offset; // silence unused variable warning + if (line > 0 && line < strip->size-1) { ASScanline *above = strip->lines[line-1]; ASScanline *below = strip->lines[line+1]; @@ -615,7 +608,8 @@ interpolate_green_diff(ASIMStrip *strip, int line, int chan, int offset) Bool interpolate_from_green_diff(ASIMStrip *strip, int line, int chan, int offset) { - int width = strip->lines[line]->width; + (void)offset; // silence unused variable warning + int width = strip->lines[line]->width; CARD32 *green = strip->lines[line]->green; CARD32 *dst = strip->lines[line]->channels[chan]; int *diff = strip->aux_data[line]; @@ -679,12 +673,13 @@ interpolate_asim_strip_custom_rggb2 (ASIMStrip *strip, ASFlagType filter, Bool f set_flags(strip->lines[line]->flags, ASIM_SCL_InterpolatedH<size-1 ; ++line) if (get_flags(strip->lines[line]->flags, SCL_DO_GREEN) diff --git a/graf2d/asimage/src/libAfterImage/test_mmx.c b/graf2d/asimage/src/libAfterImage/test_mmx.c index 4afdc61c84c62..0703071ac9e75 100644 --- a/graf2d/asimage/src/libAfterImage/test_mmx.c +++ b/graf2d/asimage/src/libAfterImage/test_mmx.c @@ -24,11 +24,7 @@ #undef DEBUG_RECTS2 #endif -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif +#include "afterbase.h" #include diff --git a/graf2d/asimage/src/libAfterImage/transform.c b/graf2d/asimage/src/libAfterImage/transform.c index 9c86e3ac9772a..838f985fcf6f3 100644 --- a/graf2d/asimage/src/libAfterImage/transform.c +++ b/graf2d/asimage/src/libAfterImage/transform.c @@ -23,11 +23,6 @@ #define USE_64BIT_FPU #undef NEED_RBITSHIFT_FUNCS -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif //#undef HAVE_MMX #ifdef DO_CLOCKING @@ -58,11 +53,7 @@ #include #endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else # include "afterbase.h" -#endif #include "asvisual.h" #include "blender.h" #include "asimage.h" @@ -148,14 +139,13 @@ static inline void enlarge_component23( register CARD32 *src, register CARD32 *dst, int *scales, int len ) {/* expected len >= 2 */ register int i = 0, k = 0; - register int c1 = src[0], c4 = src[1]; - if( scales[0] == 1 ) - {/* special processing for first element - it can be 1 - others can only be 2 or 3 */ - dst[k] = INTERPOLATE_COLOR1(src[0]) ; + register int c1 = src[0], c4; + if (scales[0] == 1) { /* special processing for first element - it can be 1 - others can only be 2 or 3 */ + dst[k] = INTERPOLATE_COLOR1(src[0]) ; ++k; ++i; - } - --len; --len ; + } + --len; --len ; while( i < len ) { register int c2 = src[i], c3 = src[i+1] ; @@ -304,18 +294,19 @@ shrink_component( register CARD32 *src, register CARD32 *dst, int *scales, int l static inline void shrink_component11( register CARD32 *src, register CARD32 *dst, int *scales, int len ) { - register int i ; - for( i = 0 ; i < len ; ++i ) - dst[i] = AVERAGE_COLOR1(src[i]); + (void)scales; // silence unused variable warning + register int i; + for (i = 0; i < len; ++i) + dst[i] = AVERAGE_COLOR1(src[i]); } - static inline void reverse_component( register CARD32 *src, register CARD32 *dst, int *unused, int len ) { - register int i = 0; - src += len-1 ; - do + (void)unused; // silence unused variable warning + register int i = 0; + src += len - 1; + do { dst[i] = src[-i]; }while(++i < len ); @@ -324,7 +315,8 @@ reverse_component( register CARD32 *src, register CARD32 *dst, int *unused, int static inline void add_component( CARD32 *src, CARD32 *incr, int *scales, int len ) { - len += len&0x01; + (void)scales; // silence unused variable warning + len += len & 0x01; #ifdef HAVE_MMX #if 1 if( asimage_use_mmx ) @@ -395,10 +387,10 @@ start_component_interpolation( CARD32 *c1, CARD32 *c2, CARD32 *c3, CARD32 *c4, r static inline void component_interpolation_hardcoded( CARD32 *c1, CARD32 *c2, CARD32 *c3, CARD32 *c4, register CARD32 *T, CARD32 *unused, CARD16 kind, int len) { - register int i; - if( kind == 1 ) - { - for( i = 0 ; i < len ; i++ ) + (void)unused; // silence unused variable warning + register int i; + if (kind == 1) { + for( i = 0 ; i < len ; i++ ) { #if 1 /* its seems that this simple formula is completely sufficient @@ -412,15 +404,14 @@ component_interpolation_hardcoded( CARD32 *c1, CARD32 *c2, CARD32 *c3, CARD32 *c (plus-minus)>>2; #endif } - }else if( kind == 2 ) - { - for( i = 0 ; i < len ; i++ ) + } else if (kind == 2) { + for( i = 0 ; i < len ; i++ ) { register int rc1 = c1[i], rc2 = c2[i], rc3 = c3[i] ; T[i] = INTERPOLATE_A_COLOR3_V(rc1,rc2,rc3,c4[i]); } - }else - for( i = 0 ; i < len ; i++ ) + } else + for( i = 0 ; i < len ; i++ ) { register int rc1 = c1[i], rc2 = c2[i], rc3 = c3[i] ; T[i] = INTERPOLATE_B_COLOR3_V(rc1,rc2,rc3,c4[i]); @@ -447,9 +438,10 @@ rbitshift_component_mod( register CARD32 *data, int bits, int len ) void print_component( register CARD32 *data, int nonsense, int len ) { - register int i ; - for( i = 0 ; i < len ; ++i ) - fprintf( stderr, " %8.8lX", (long)data[i] ); + (void)nonsense; // silence unused variable warning + register int i; + for (i = 0; i < len; ++i) + fprintf( stderr, " %8.8lX", (long)data[i] ); fprintf( stderr, "\n"); } @@ -500,9 +492,9 @@ copytintpad_scanline( ASScanline *src, ASScanline *dst, int offset, ARGB32 tint register int i ; CARD32 chan_tint[4], chan_fill[4] ; int color ; - int copy_width = src->width, dst_offset = 0, src_offset = 0; + int copy_width, dst_offset = 0, src_offset = 0; - if( offset+(int)src->width < 0 || offset > (int)dst->width ) + if( offset+(int)src->width < 0 || offset > (int)dst->width ) return; chan_tint[IC_RED] = ARGB32_RED8 (tint)<<1; chan_tint[IC_GREEN] = ARGB32_GREEN8(tint)<<1; @@ -901,24 +893,23 @@ scale_asimage( ASVisual *asv, ASImage *src, int to_width, int to_height, dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color ); - if( to_width == src->width ) - h_ratio = 0; - else if( to_width < src->width ) - h_ratio = 1; - else - { - if ( quality == ASIMAGE_QUALITY_POOR ) + if (to_width == (int)src->width) + h_ratio = 0; + else if (to_width < (int)src->width) + h_ratio = 1; + else { + if ( quality == ASIMAGE_QUALITY_POOR ) h_ratio = 1 ; else if( src->width > 1 ) { h_ratio = (to_width/(src->width-1))+1; - if( h_ratio*(src->width-1) < to_width ) - ++h_ratio ; - }else - h_ratio = to_width ; + if (h_ratio * ((int)src->width - 1) < to_width) + ++h_ratio; + } else + h_ratio = to_width ; ++h_ratio ; - } - scales_h = make_scales( src->width, to_width, ( quality == ASIMAGE_QUALITY_POOR )?0:1 ); + } + scales_h = make_scales( src->width, to_width, ( quality == ASIMAGE_QUALITY_POOR )?0:1 ); scales_v = make_scales( src->height, to_height, ( quality == ASIMAGE_QUALITY_POOR || src->height <= 3)?0:1 ); #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT) { @@ -936,10 +927,10 @@ scale_asimage( ASVisual *asv, ASImage *src, int to_width, int to_height, destroy_asimage( &dst ); }else { - if( to_height <= src->height ) /* scaling down */ - scale_image_down( imdec, imout, h_ratio, scales_h, scales_v ); - else if( quality == ASIMAGE_QUALITY_POOR || src->height <= 3 ) - scale_image_up_dumb( imdec, imout, h_ratio, scales_h, scales_v ); + if (to_height <= (int)src->height) /* scaling down */ + scale_image_down(imdec, imout, h_ratio, scales_h, scales_v); + else if (quality == ASIMAGE_QUALITY_POOR || src->height <= 3) + scale_image_up_dumb( imdec, imout, h_ratio, scales_h, scales_v ); else scale_image_up( imdec, imout, h_ratio, scales_h, scales_v ); stop_image_output( &imout ); @@ -1063,29 +1054,25 @@ LOCAL_DEBUG_CALLER_OUT( "src = %p, offset_x = %d, offset_y = %d, to_width = %d, { int y, max_y = to_height; LOCAL_DEBUG_OUT("tiling actually...%s", ""); - if( to_height > src->height ) - { - imout->tiling_step = src->height ; - max_y = src->height ; - } - if( tint != 0 ) - { - for( y = 0 ; y < max_y ; y++ ) - { - imdec->decode_image_scanline( imdec ); - tint_component_mod( imdec->buffer.red, (CARD16)(ARGB32_RED8(tint)<<1), to_width ); - tint_component_mod( imdec->buffer.green, (CARD16)(ARGB32_GREEN8(tint)<<1), to_width ); - tint_component_mod( imdec->buffer.blue, (CARD16)(ARGB32_BLUE8(tint)<<1), to_width ); - tint_component_mod( imdec->buffer.alpha, (CARD16)(ARGB32_ALPHA8(tint)<<1), to_width ); - imout->output_image_scanline( imout, &(imdec->buffer), 1); - } - }else - for( y = 0 ; y < max_y ; y++ ) - { - imdec->decode_image_scanline( imdec ); - imout->output_image_scanline( imout, &(imdec->buffer), 1); - } - stop_image_output( &imout ); +if (to_height > (int)src->height) { + imout->tiling_step = src->height; + max_y = src->height; +} +if (tint != 0) { + for (y = 0; y < max_y; y++) { + imdec->decode_image_scanline(imdec); + tint_component_mod(imdec->buffer.red, (CARD16)(ARGB32_RED8(tint) << 1), to_width); + tint_component_mod(imdec->buffer.green, (CARD16)(ARGB32_GREEN8(tint) << 1), to_width); + tint_component_mod(imdec->buffer.blue, (CARD16)(ARGB32_BLUE8(tint) << 1), to_width); + tint_component_mod(imdec->buffer.alpha, (CARD16)(ARGB32_ALPHA8(tint) << 1), to_width); + imout->output_image_scanline(imout, &(imdec->buffer), 1); + } +} else + for (y = 0; y < max_y; y++) { + imdec->decode_image_scanline(imdec); + imout->output_image_scanline(imout, &(imdec->buffer), 1); + } + stop_image_output( &imout ); } stop_image_decoding( &imdec ); @@ -1255,10 +1242,11 @@ LOCAL_DEBUG_OUT( "min_y = %d, max_y = %d", min_y, max_y ); static void make_gradient_left2right( ASImageOutput *imout, ASScanline *dither_lines, int dither_lines_num, ASFlagType filter ) { - int line ; + (void)filter; // silence unused variable warning + int line; - imout->tiling_step = dither_lines_num; - for( line = 0 ; line < dither_lines_num ; line++ ) + imout->tiling_step = dither_lines_num; + for( line = 0 ; line < dither_lines_num ; line++ ) imout->output_image_scanline( imout, &(dither_lines[line]), 1); } @@ -1328,9 +1316,10 @@ LOCAL_DEBUG_CALLER_OUT( "width = %d, height = %d, filetr = 0x%lX, dither_count = static void make_gradient_diag_width( ASImageOutput *imout, ASScanline *dither_lines, int dither_lines_num, ASFlagType filter, Bool from_bottom ) { - int line = 0; - /* using bresengham algorithm again to trigger horizontal shift : */ - short smaller = imout->im->height; + (void)filter; // silence unused variable warning + int line = 0; + /* using bresengham algorithm again to trigger horizontal shift : */ + short smaller = imout->im->height; short bigger = imout->im->width; register int i = 0; int eps; @@ -1735,10 +1724,10 @@ LOCAL_DEBUG_CALLER_OUT( "dst_x = %d, dst_y = %d, to_width = %d, to_height = %d", if( src == NULL ) return NULL ; - if( to_width == src->width && to_height == src->height && dst_x == 0 && dst_y == 0 ) - return clone_asimage( src, SCL_DO_ALL ); + if (to_width == (int)src->width && to_height == (int)src->height && dst_x == 0 && dst_y == 0) + return clone_asimage(src, SCL_DO_ALL); - if( asv == NULL ) asv = &__transform_fake_asv ; + if( asv == NULL ) asv = &__transform_fake_asv ; dst = create_destination_image( to_width, to_height, out_format, compression_out, src->back_color); @@ -2290,9 +2279,9 @@ load_gauss_scanline(ASScanline *result, ASImageDecoder *imdec, int horz, GAUSS_C { if( horz == 1 ) { - for( x = 0 ; x < result->width ; ++x ) - res_chan[x] = src_chan[x]<<10 ; - }else + for (x = 0; x < (int)result->width; ++x) + res_chan[x] = src_chan[x] << 10; + }else { #ifdef USE_PARALLEL_OPTIMIZATION todo[todo_count++] = chan; @@ -2305,9 +2294,10 @@ load_gauss_scanline(ASScanline *result, ASImageDecoder *imdec, int horz, GAUSS_C else if( get_flags( filter, 0x01<buffer.back_color)<<10; - for( x = 0 ; x < result->width ; ++x ) res_chan[x] = fill ; - } - } + for (x = 0; x < (int)result->width; ++x) + res_chan[x] = fill; + } + } #ifdef USE_PARALLEL_OPTIMIZATION switch( 4 - todo_count ) @@ -2390,14 +2380,12 @@ ASImage* blur_asimage_gauss(ASVisual* asv, ASImage* src, double dhorz, double dv if( vert == 1 && horz == 1 ) { - for (y = 0 ; y < dst->height ; y++) - { - imdec->decode_image_scanline(imdec); - imout->output_image_scanline(imout, &(imdec->buffer), 1); - } - }else - { - ASScanline result; + for (y = 0; y < (int)dst->height; y++) { + imdec->decode_image_scanline(imdec); + imout->output_image_scanline(imout, &(imdec->buffer), 1); + } + } else { + ASScanline result; GAUSS_COEFF_TYPE *horz_gauss = NULL; GAUSS_COEFF_TYPE *horz_gauss_sums = NULL; @@ -2501,12 +2489,13 @@ ASImage* blur_asimage_gauss(ASVisual* asv, ASImage* src, double dhorz, double dv register ASScanline **ysrc = &lines[y]; /* surprisingly, having x loops inside y loop yields 30% to 80% better performance */ int j = 0; - CARD32 *src_chan1 = ysrc[0]->channels[chan]; - memset( res_chan, 0x00, width*4 ); -/* for( x = 0 ; x < width ; ++x ) - res_chan[x] = src_chan1[x]*vert_gauss[0]; - */ - while( ++j < vert ) + CARD32 *src_chan1; + memset( res_chan, 0x00, width*4 ); + /* src_chan1 = ysrc[0]->channels[chan]; + for( x = 0 ; x < width ; ++x ) + res_chan[x] = src_chan1[x]*vert_gauss[0]; + */ + while( ++j < vert ) { CARD32 *src_chan2 = ysrc[j]->channels[chan]; GAUSS_COEFF_TYPE g = vert_gauss[j]; @@ -2618,7 +2607,7 @@ ASImage* blur_asimage_gauss(ASVisual* asv, ASImage* src, double dhorz, double dv free(horz_gauss_sums); if( horz_gauss ) free(horz_gauss); - } + } PRINT_BACKGROUND_OP_TIME; stop_image_decoding(&imdec); @@ -2847,23 +2836,19 @@ LOCAL_DEBUG_CALLER_OUT( "offset_x = %d, offset_y = %d, to_width = %d, to_height saturation_offset = (saturation_offset<<16) / 100; value_offset = (value_offset<<16)/100 ; LOCAL_DEBUG_OUT("adjusting actually...%s", ""); - if( to_height > src->height ) - { - imout->tiling_step = src->height ; - max_y = src->height ; - } - for( y = 0 ; y < max_y ; y++ ) - { - register int x = imdec->buffer.width; - CARD32 *r = imdec->buffer.red; - CARD32 *g = imdec->buffer.green; - CARD32 *b = imdec->buffer.blue ; - long h, s, v ; - imdec->decode_image_scanline( imdec ); - while( --x >= 0 ) - { - if( (h = rgb2hue( r[x], g[x], b[x] )) != 0 ) - { +if (to_height > (int)src->height) { + imout->tiling_step = src->height; + max_y = src->height; +} +for (y = 0; y < max_y; y++) { + register int x = imdec->buffer.width; + CARD32 *r = imdec->buffer.red; + CARD32 *g = imdec->buffer.green; + CARD32 *b = imdec->buffer.blue; + long h, s, v; + imdec->decode_image_scanline(imdec); + while (--x >= 0) { + if ((h = rgb2hue(r[x], g[x], b[x])) != 0) { #ifdef DEBUG_HSV_ADJUSTMENT fprintf( stderr, "IN %d: rgb = #%4.4lX.%4.4lX.%4.4lX hue = %ld(%d) range is (%ld - %ld, %ld - %ld), dh = %d\n", __LINE__, r[x], g[x], b[x], h, ((h>>8)*360)>>8, from_hue1, to_hue1, from_hue2, to_hue2, hue_offset ); #endif @@ -2902,8 +2887,8 @@ LOCAL_DEBUG_OUT("adjusting actually...%s", ""); } imdec->buffer.flags = 0xFFFFFFFF ; imout->output_image_scanline( imout, &(imdec->buffer), 1); - } - stop_image_output( &imout ); +} + stop_image_output( &imout ); } stop_image_decoding( &imdec ); @@ -2931,9 +2916,9 @@ slice_scanline( ASScanline *dst, ASScanline *src, int start_x, int end_x, ASScan dg[x1] = sg[x1] ; db[x1] = sb[x1] ; } - if( x1 >= dst->width ) - return; - /* middle portion */ + if (x1 >= (int)dst->width) + return; + /* middle portion */ max_x2 = (int) dst->width - tail ; max_x = min(end_x, max_x2); if( middle ) @@ -2956,15 +2941,13 @@ slice_scanline( ASScanline *dst, ASScanline *src, int start_x, int end_x, ASScan { for( ; x1 < max_x ; ++x1 ) { - x2 = x1 ; - for( x2 = x1 ; x2 < max_x2 ; x2 += tiling_step ) - { - da[x2] = sa[x1] ; + for (x2 = x1; x2 < max_x2; x2 += tiling_step) { + da[x2] = sa[x1] ; dr[x2] = sr[x1] ; dg[x2] = sg[x1] ; - db[x2] = sb[x1] ; - } - } + db[x2] = sb[x1] ; + } + } } /* tail portion */ x1 = src->width - tail ; @@ -3007,11 +2990,11 @@ LOCAL_DEBUG_CALLER_OUT( "scale = %d, sx1 = %d, sx2 = %d, sy1 = %d, sy2 = %d, to_ slice_x_end = slice_x_start + 1 ; if( slice_y_end == 0 && slice_y_start > 0 ) slice_y_end = slice_y_start + 1 ; - if( slice_x_end > src->width ) - slice_x_end = src->width ; - if( slice_y_end > src->height ) - slice_y_end = src->height ; - if( slice_x_start > slice_x_end ) + if (slice_x_end > (int)src->width) + slice_x_end = src->width; + if (slice_y_end > (int)src->height) + slice_y_end = src->height; + if( slice_x_start > slice_x_end ) slice_x_start = (slice_x_end > 0 ) ? slice_x_end-1 : 0 ; if( slice_y_start > slice_y_end ) slice_y_start = (slice_y_end > 0 ) ? slice_y_end-1 : 0 ; @@ -3113,9 +3096,9 @@ LOCAL_DEBUG_OUT( "sx1 = %d, sx2 = %d, sy1 = %d, sy2 = %d, to_width = %d, to_heig imout->next_line = y2 ; imdec->next_line = y1 ; max_y = src->height ; - if( y2 + max_y - y1 > dst->height ) - max_y = dst->height + y1 - y2 ; - LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d", y1, max_y ); + if (y2 + max_y - y1 > (int)dst->height) + max_y = dst->height + y1 - y2; + LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d", y1, max_y ); if( x_middle > 0 ) { tmp = scale_asimage2( asv, src, slice_x_start, y1, @@ -3166,9 +3149,9 @@ LOCAL_DEBUG_OUT( "sx1 = %d, sx2 = %d, sy1 = %d, sy2 = %d, to_width = %d, to_heig imout->next_line = y2 = max(max_y2,(int)slice_y_start) ; imdec->next_line = y1 = src->height - tail ; max_y = src->height ; - if( y2 + max_y - y1 > dst->height ) - max_y = dst->height + y1 - y2 ; - LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d", y1, max_y ); + if (y2 + max_y - y1 > (int)dst->height) + max_y = dst->height + y1 - y2; + LOCAL_DEBUG_OUT( "y1 = %d, max_y = %d", y1, max_y ); for( ; y1 < max_y ; ++y1 ) { imdec->decode_image_scanline( imdec ); @@ -3381,10 +3364,9 @@ fprintf (stderr, "color2alpha():%d: color: red = 0x%8.8X green = 0x%8.8X blue = int x ; ASScanline *srcsl = &(imdec->buffer); imdec->decode_image_scanline( imdec ); - for (x = 0; x < imdec->buffer.width; ++x) - { - CARD32 r = srcsl->red[x]; - CARD32 g = srcsl->green[x]; + for (x = 0; x < (int)imdec->buffer.width; ++x) { + CARD32 r = srcsl->red[x]; + CARD32 g = srcsl->green[x]; CARD32 b = srcsl->blue[x]; CARD32 a = srcsl->alpha[x]; /* the following logic is stolen from gimp and altered for our color format and beauty*/ @@ -3430,9 +3412,9 @@ fprintf (stderr, "result: %8.8X %8.8X %8.8X %8.8X.\n", src->alpha[x], src->red[x } /* end of gimp code */ - } - imout->output_image_scanline( imout, srcsl, 1); - } + } + imout->output_image_scanline(imout, srcsl, 1); + } stop_image_output( &imout ); } stop_image_decoding( &imdec ); diff --git a/graf2d/asimage/src/libAfterImage/ungif.c b/graf2d/asimage/src/libAfterImage/ungif.c index c9679bfd86f9f..7db90a4583377 100644 --- a/graf2d/asimage/src/libAfterImage/ungif.c +++ b/graf2d/asimage/src/libAfterImage/ungif.c @@ -19,12 +19,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - /*#define LOCAL_DEBUG */ /*#define DO_CLOCKING */ @@ -50,11 +44,7 @@ #include #include -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #ifdef HAVE_GIF # include #endif @@ -223,7 +213,7 @@ get_gif_saved_images( GifFileType *gif, int subimage, SavedImage **ret, int *ret ExtCode, ExtData[0], &(ExtData[1])); #else temp_save.Function = ExtCode; - status = AddExtensionBlock(&temp_save, ExtData[0], (char*)&(ExtData[1])); + status = AddExtensionBlock(&temp_save, ExtData[0], (unsigned char *)&(ExtData[1])); #endif if (status == GIF_OK) status = DGifGetExtensionNext(gif, &ExtData); diff --git a/graf2d/asimage/src/libAfterImage/win32/StdAfx.cpp b/graf2d/asimage/src/libAfterImage/win32/StdAfx.cpp deleted file mode 100644 index 0719ce237d290..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/StdAfx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// asview.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/graf2d/asimage/src/libAfterImage/win32/StdAfx.h b/graf2d/asimage/src/libAfterImage/win32/StdAfx.h deleted file mode 100644 index ae1ba446d2356..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/StdAfx.h +++ /dev/null @@ -1,28 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) -#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -#include - - -// TODO: reference additional headers your program requires here -#include "config.h" -#include -#include "afterbase.h" -#include "../afterimage.h" -#include "../bmp.h" - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) diff --git a/graf2d/asimage/src/libAfterImage/win32/afterbase.h b/graf2d/asimage/src/libAfterImage/win32/afterbase.h deleted file mode 100644 index 39cf553d03c97..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/afterbase.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef AFTERBASE_H_HEADER_INCLUDED -#define AFTERBASE_H_HEADER_INCLUDED - -#define HAVE_AFTERBASE_FLAG 0 - - -# include "../asim_afterbase.h" - -#define R_OK 04 - -#endif /* AFTERBASE_H_HEADER_INCLUDED */ - diff --git a/graf2d/asimage/src/libAfterImage/win32/asview.cpp b/graf2d/asimage/src/libAfterImage/win32/asview.cpp deleted file mode 100644 index 5f89d0aad5f33..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/asview.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// asview.cpp : Defines the entry point for the application. -// - -#include "stdafx.h" - -void usage() -{ - printf( "Usage: asview [-h]|[image]\n"); - printf( "Where: image - filename of the image to display.\n"); -} - -LRESULT CALLBACK MyWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); -void show_system_error(); - - -HINSTANCE hinst; -HWND hWnd = NULL ; -void *bmbits = NULL ; -BITMAPINFO *bmi = NULL ; - - -int APIENTRY -WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow) -{ - char *image_file = "../apps/rose512.jpg" ; - -// char *image_file = "../apps/fore.xpm" ; - ASImage *im ; - WNDCLASSEX wnd_class ; - ASVisual *asv ; - MSG msg; - - if( lpCmdLine != NULL && strncmp( lpCmdLine, "-h", 2 ) == 0 ) - { - usage(); - return 0; - }else if( lpCmdLine != NULL && strlen(lpCmdLine) > 0 ) - image_file = lpCmdLine ; - else - usage(); - - if( image_file[0] == '\"' ) - { - int i = 0; - while( image_file[i+1] != '\0' && image_file[i+1] != '\"') - { - image_file[i] = image_file[i+1] ; - ++i ; - } - image_file[i] = '\0' ; - } - - asv = create_asvisual( NULL, 0, 0, NULL ); - - im = file2ASImage( image_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, NULL ); - if( im == NULL ) - { - MessageBox( NULL, "Unable to load image from file.", image_file, MB_OK | MB_ICONINFORMATION ); - return 0 ; - } - - /* converting result into BMP file ( as an example ) */ - /* ASImage2file( im, NULL, "asview.bmp", ASIT_Bmp, NULL ); */ - - /* The following could be used to dump JPEG version of the image into - * stdout : */ - /* ASImage2file( im, NULL, NULL, ASIT_Jpeg, NULL ); */ - - - bmbits = NULL ; - // Convert ASImage into DIB: - bmi = ASImage2DBI( asv, im, 0, 0, im->width, im->height, &bmbits ); - - if( bmi == NULL ) - { - MessageBox( NULL, "Failed to convert image into Windows bitmap.", image_file, MB_OK | MB_ICONINFORMATION ); - return 0 ; - } - - memset( &wnd_class, 0x00, sizeof(wnd_class)); - wnd_class.cbSize = sizeof(wnd_class); - wnd_class.hInstance = hInstance ; - wnd_class.lpszClassName = "ASView" ; - wnd_class.lpfnWndProc = MyWindowProc ; - wnd_class.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); - wnd_class.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); - wnd_class.hbrBackground = (struct HBRUSH__ *)GetStockObject(WHITE_BRUSH); - - if( !RegisterClassEx( &wnd_class ) ) - { - show_system_error(); - return 0 ; - } - - hinst = hInstance ; - /* Now let us create a window and display image in that window : */ - hWnd = CreateWindow( "ASView", image_file, - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, - bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, - (HWND) NULL, (HMENU)NULL, hinst, NULL ); - if (!hWnd) - { - show_system_error(); - return FALSE; - } - - // Show the window and paint its contents. - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); - - // Start the message loop. - while (GetMessage(&msg, hWnd, 0, 0) > 0 ) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return 0; -} - -LRESULT CALLBACK -MyWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - if( uMsg == WM_PAINT ) - { - // Paint image in responce to WM_PAINT event : - if( bmi != NULL && bmbits != NULL ) - { - PAINTSTRUCT ps ; - HDC dc = BeginPaint(hWnd, &ps ); - StretchDIBits( dc, // handle to device context - 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, - 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, - bmbits, bmi, DIB_RGB_COLORS, SRCCOPY ); - EndPaint(hWnd, &ps ); - - } - return 0; - } - - return DefWindowProc( hwnd, uMsg, wParam, lParam ) ; -} - -void -show_system_error() -{ - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, - 0, NULL ); - MessageBox( NULL, (LPCTSTR)lpMsgBuf, "ASView System Error", MB_OK | MB_ICONINFORMATION ); - // Free the buffer. - LocalFree( lpMsgBuf ); -} - - diff --git a/graf2d/asimage/src/libAfterImage/win32/asview.dsp b/graf2d/asimage/src/libAfterImage/win32/asview.dsp deleted file mode 100644 index af83fef23adc9..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/asview.dsp +++ /dev/null @@ -1,122 +0,0 @@ -# Microsoft Developer Studio Project File - Name="asview" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Application" 0x0101 - -CFG=asview - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "asview.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "asview.mak" CFG="asview - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "asview - Win32 Release" (based on "Win32 (x86) Application") -!MESSAGE "asview - Win32 Debug" (based on "Win32 (x86) Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "asview - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"LIBCD" /nodefaultlib:"LIBC" /out:"asview.exe" /editandcontinue:NO -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "asview - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "asview___Win32_Debug" -# PROP BASE Intermediate_Dir "asview___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBC" /out:"asview.exe" /pdbtype:sept -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "asview - Win32 Release" -# Name "asview - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\asview.cpp -# End Source File -# Begin Source File - -SOURCE=.\StdAfx.cpp -# ADD CPP /Yc"stdafx.h" -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\StdAfx.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# Begin Source File - -SOURCE=..\libAfterImage.lib -# End Source File -# End Target -# End Project diff --git a/graf2d/asimage/src/libAfterImage/win32/asview.mak b/graf2d/asimage/src/libAfterImage/win32/asview.mak deleted file mode 100644 index ee1bd8cd616e9..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/asview.mak +++ /dev/null @@ -1,229 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Based on asview.dsp -!IF "$(CFG)" == "" -CFG=asview - Win32 Debug -!MESSAGE No configuration specified. Defaulting to asview - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "asview - Win32 Release" && "$(CFG)" != "asview - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "asview.mak" CFG="asview - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "asview - Win32 Release" (based on "Win32 (x86) Application") -!MESSAGE "asview - Win32 Debug" (based on "Win32 (x86) Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "asview - Win32 Release" - -OUTDIR=.\Release -INTDIR=.\Release - -!IF "$(RECURSE)" == "0" - -ALL : ".\asview.exe" - -!ELSE - -ALL : "libAfterImage - Win32 Release" ".\asview.exe" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN :"libAfterImage - Win32 ReleaseCLEAN" -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\asview.obj" - -@erase "$(INTDIR)\asview.pch" - -@erase "$(INTDIR)\StdAfx.obj" - -@erase "$(INTDIR)\vc60.idb" - -@erase ".\asview.exe" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)\asview.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\asview.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\asview.pdb" /machine:I386 /nodefaultlib:"LIBCD" /out:"asview.exe" /editandcontinue:NO -LINK32_OBJS= \ - "$(INTDIR)\asview.obj" \ - "$(INTDIR)\StdAfx.obj" \ - "..\libAfterImage.lib" - -".\asview.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "asview - Win32 Debug" - -OUTDIR=.\Debug -INTDIR=.\Debug - -!IF "$(RECURSE)" == "0" - -ALL : ".\asview.exe" - -!ELSE - -ALL : "libAfterImage - Win32 Debug" ".\asview.exe" - -!ENDIF - -!IF "$(RECURSE)" == "1" -CLEAN :"libAfterImage - Win32 DebugCLEAN" -!ELSE -CLEAN : -!ENDIF - -@erase "$(INTDIR)\asview.obj" - -@erase "$(INTDIR)\asview.pch" - -@erase "$(INTDIR)\StdAfx.obj" - -@erase "$(INTDIR)\vc60.idb" - -@erase "$(INTDIR)\vc60.pdb" - -@erase "$(OUTDIR)\asview.pdb" - -@erase ".\asview.exe" - -@erase ".\asview.ilk" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)\asview.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\asview.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:yes /pdb:"$(OUTDIR)\asview.pdb" /debug /machine:I386 /nodefaultlib:"LIBC" /out:"asview.exe" /pdbtype:sept -LINK32_OBJS= \ - "$(INTDIR)\asview.obj" \ - "$(INTDIR)\StdAfx.obj" \ - "..\libAfterImage.lib" - -".\asview.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - - -!IF "$(NO_EXTERNAL_DEPS)" != "1" -!IF EXISTS("asview.dep") -!INCLUDE "asview.dep" -!ELSE -!MESSAGE Warning: cannot find "asview.dep" -!ENDIF -!ENDIF - - -!IF "$(CFG)" == "asview - Win32 Release" || "$(CFG)" == "asview - Win32 Debug" -SOURCE=.\asview.cpp - -"$(INTDIR)\asview.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\asview.pch" - - -SOURCE=.\StdAfx.cpp - -!IF "$(CFG)" == "asview - Win32 Release" - -CPP_SWITCHES=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)\asview.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -"$(INTDIR)\StdAfx.obj" "$(INTDIR)\asview.pch" : $(SOURCE) "$(INTDIR)" - $(CPP) @<< - $(CPP_SWITCHES) $(SOURCE) -<< - - -!ELSEIF "$(CFG)" == "asview - Win32 Debug" - -CPP_SWITCHES=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)\asview.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c - -"$(INTDIR)\StdAfx.obj" "$(INTDIR)\asview.pch" : $(SOURCE) "$(INTDIR)" - $(CPP) @<< - $(CPP_SWITCHES) $(SOURCE) -<< - - -!ENDIF - -!IF "$(CFG)" == "asview - Win32 Release" - -"libAfterImage - Win32 Release" : - cd "\devel\AfterStep\afterstep-stable\libAfterImage" - $(MAKE) /$(MAKEFLAGS) /F ".\libAfterImage.mak" CFG="libAfterImage - Win32 Release" - cd ".\win32" - -"libAfterImage - Win32 ReleaseCLEAN" : - cd "\devel\AfterStep\afterstep-stable\libAfterImage" - $(MAKE) /$(MAKEFLAGS) /F ".\libAfterImage.mak" CFG="libAfterImage - Win32 Release" RECURSE=1 CLEAN - cd ".\win32" - -!ELSEIF "$(CFG)" == "asview - Win32 Debug" - -"libAfterImage - Win32 Debug" : - cd "\devel\AfterStep\afterstep-stable\libAfterImage" - $(MAKE) /$(MAKEFLAGS) /F ".\libAfterImage.mak" CFG="libAfterImage - Win32 Debug" - cd ".\win32" - -"libAfterImage - Win32 DebugCLEAN" : - cd "\devel\AfterStep\afterstep-stable\libAfterImage" - $(MAKE) /$(MAKEFLAGS) /F ".\libAfterImage.mak" CFG="libAfterImage - Win32 Debug" RECURSE=1 CLEAN - cd ".\win32" - -!ENDIF - - -!ENDIF - diff --git a/graf2d/asimage/src/libAfterImage/win32/config.h b/graf2d/asimage/src/libAfterImage/win32/config.h deleted file mode 100644 index f1a288c8a83f5..0000000000000 --- a/graf2d/asimage/src/libAfterImage/win32/config.h +++ /dev/null @@ -1,171 +0,0 @@ -/* config.h.in. Generated from configure.in by autoheader. */ -#ifndef WIN32_CONFIG_H -#define WIN32_CONFIG_H -/* Define if memory allocation logging and debugging is desired */ -#undef DEBUG_ALLOCS - -/* Define if libAfterBase is available */ -#undef HAVE_AFTERBASE - -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -#define HAVE_BOOLEAN -typedef unsigned char boolean; - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define if libFreeType is available - should always be under win32 ! */ -#define HAVE_FREETYPE 1 - -/* Define if libFreeType is available */ -#define HAVE_FREETYPE_FREETYPE 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FT2BUILD_H 1 - -#if _MSC_VER >= 1400 -#define NO_DOUBLE_FCLOSE_AFTER_FDOPEN -#else -/*#undef NO_DOUBLE_FCLOSE_AFTER_FDOPEN */ -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define if libjpeg is available */ -#define HAVE_JPEG 1 - -/* Define if support for XPM images should be through libXpm */ -#undef HAVE_LIBXPM - -/* Define if support for XPM images should be through libXpm library in Xlib - */ -#undef HAVE_LIBXPM_X11 - -/* Define to 1 if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define if CPU supports MMX instructions */ -#undef HAVE_MMX - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define if libpng is available */ -#define HAVE_PNG 1 - -/* We always use function prototypes - not supporting old compilers */ -#define HAVE_PROTOTYPES 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDDEF_H 1 - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H /* VC++ does not have that ! */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_DIRENT_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define if libtiff is available */ -#undef HAVE_TIFF - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define if support for XPM images is desired */ -#define HAVE_XPM 1 - -/* Define to 1 if you have the header file. */ -// 16 Mar 2026: With a system or builtin zlib, the file is there by definition -#define HAVE_ZLIB_H 1 - -/* Define if locale support in X is needed */ -#undef I18N - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "as-bugs@afterstep.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libAfterImage" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libAfterImage 0.99" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libAfterImage.tar" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.99" - -/* Support for shaped windows */ -#undef SHAPE - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#undef TIME_WITH_SYS_TIME - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#undef WORDS_BIGENDIAN - -/* Define if support for shared memory XImages is available */ -#undef XSHMIMAGE - -/* Define to 1 if the X Window System is missing or not being used. */ -#define X_DISPLAY_MISSING 1 - -/* Define to 1 if type `char' is unsigned and you are not using gcc. */ -#ifndef __CHAR_UNSIGNED__ -# undef __CHAR_UNSIGNED__ -#endif - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -#define inline - -#endif \ No newline at end of file diff --git a/graf2d/asimage/src/libAfterImage/xcf.c b/graf2d/asimage/src/libAfterImage/xcf.c index 1718dc0cb7d0c..0526ac8dff617 100644 --- a/graf2d/asimage/src/libAfterImage/xcf.c +++ b/graf2d/asimage/src/libAfterImage/xcf.c @@ -18,12 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - /*#define LOCAL_DEBUG*/ /*#define DO_CLOCKING*/ @@ -42,11 +36,7 @@ # endif #endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #include "asimage.h" #include "xcf.h" @@ -697,7 +687,9 @@ read_xcf_levels( XcfImage *xcf_im, FILE *fp, XcfLevel *head ) static void read_xcf_tiles( XcfImage *xcf_im, FILE *fp, XcfTile *head ) { - while( head ) + (void)xcf_im; + (void)fp; // silence unused variable warning + while( head ) { head->estimated_size = XCF_TILE_WIDTH*XCF_TILE_HEIGHT*4 ; head = head->next ; @@ -708,7 +700,9 @@ read_xcf_tiles( XcfImage *xcf_im, FILE *fp, XcfTile *head ) static void read_xcf_tiles_rle( XcfImage *xcf_im, FILE *fp, XcfTile *head ) { - while( head ) + (void)xcf_im; + (void)fp; // silence unused variable warning + while( head ) { if( head->next ) head->estimated_size = head->next->offset - head->offset ; @@ -745,7 +739,9 @@ void decode_xcf_tile( FILE *fp, XcfTile *tile, int bpp, ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height) { - int bytes_in, available = width*height ; + (void)tile; + (void)offset_y; // silence unused variable warning + int bytes_in, available = width*height ; int y = 0; int comp = 0 ; @@ -769,8 +765,10 @@ void decode_xcf_tile_rle( FILE *fp, XcfTile *tile, int bpp, ASScanline *buf, CARD8* tile_buf, int offset_x, int offset_y, int width, int height) { - int bytes_in, available = width*height ; - int x = 0, y = 0; + (void)tile; + (void)offset_y; // silence unused variable warning + int bytes_in, available = width * height; + int x = 0, y = 0; CARD8 tmp[XCF_TILE_WIDTH] ; int comp = 0 ; diff --git a/graf2d/asimage/src/libAfterImage/ximage.c b/graf2d/asimage/src/libAfterImage/ximage.c index 5c2577eb792d0..9f63720258612 100644 --- a/graf2d/asimage/src/libAfterImage/ximage.c +++ b/graf2d/asimage/src/libAfterImage/ximage.c @@ -16,12 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WIN32 -#include "win32/config.h" -#else -#include "config.h" -#endif - #undef LOCAL_DEBUG #define DO_CLOCKING @@ -47,12 +41,7 @@ /*# include */ #endif - -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #include "asvisual.h" #include "blender.h" #include "asimage.h" @@ -421,7 +410,15 @@ pixmap2ximage(ASVisual *asv, Pixmap p, int x, int y, unsigned int width, unsigne } return im; #else - return NULL ; + (void)asv; + (void)p; + (void)x; + (void)y; + (void)width; + (void)height; + (void)plane_mask; + (void)compression; // silence unused variable warning + return NULL; #endif } @@ -454,7 +451,17 @@ picture2asimage(ASVisual *asv, Pixmap rgb, Pixmap a , int x, int y, unsigned int } return im; #else - return NULL ; + (void)asv; + (void)rgb; + (void)a; + (void)x; + (void)y; + (void)width; + (void)height; + (void)plane_mask; + (void)keep_cache; + (void)compression; // silence unused variable warning + return NULL; #endif } @@ -478,28 +485,36 @@ put_ximage( ASVisual *asv, XImage *xim, Drawable d, GC gc, src_x = 0; }else if( src_x > xim->width ) return False; - if( xim->width > src_x+width ) - width = xim->width - src_x ; - if( src_y < 0 ) - { - height+= src_y ; - src_y = 0; - }else if( src_y > xim->height ) - return False; - if( xim->height > src_y+height ) - height = xim->height - src_y ; - - if( my_gc == NULL ) - { - XGCValues gcv ; - my_gc = XCreateGC( asv->dpy, d, 0, &gcv ); - } - ASPutXImage( asv, d, my_gc, xim, src_x, src_y, dest_x, dest_y, width, height ); - if( my_gc != gc ) + if (xim->width > src_x + (int)width) + width = xim->width - src_x; + if (src_y < 0) { + height += src_y; + src_y = 0; + } else if (src_y > xim->height) + return False; + if (xim->height > src_y + (int)height) + height = xim->height - src_y; + + if (my_gc == NULL) { + XGCValues gcv; + my_gc = XCreateGC( asv->dpy, d, 0, &gcv ); + } + ASPutXImage(asv, d, my_gc, xim, src_x, src_y, dest_x, dest_y, width, height); + if( my_gc != gc ) XFreeGC( asv->dpy, my_gc ); return True ; #else - return False ; + (void)asv; + (void)xim; + (void)d; + (void)gc; + (void)src_x; + (void)src_y; + (void)dest_x; + (void)dest_y; + (void)width; + (void)height; // silence unused variable warning + return False; #endif } @@ -640,6 +655,16 @@ asimage2drawable_gl( ASVisual *asv, Drawable d, ASImage *im, glXDestroyGLXPixmap( asv->dpy, glxp); glFinish(); return True; +#else + (void)src_x; + (void)src_y; + (void)dest_x; + (void)dest_y; + (void)width; + (void)height; + (void)d_width; + (void)d_height; + (void)force_direct; // silence unused variable warning #endif /* #ifdef HAVE_GLX */ } { @@ -685,6 +710,18 @@ asimage2drawable( ASVisual *asv, Drawable d, ASImage *im, GC gc, } return res; } +#else + (void)asv; + (void)d; + (void)im; + (void)gc; + (void)src_x; + (void)src_y; + (void)dest_x; + (void)dest_y; + (void)width; + (void)height; + (void)use_cached; // silence unused variable warning #endif return False ; } @@ -705,15 +742,14 @@ asimage2alpha_drawable( ASVisual *asv, Drawable d, ASImage *im, GC gc, XGetGeometry( asv->dpy, d, &root, &dumm, &dumm, &udumm, &udumm, &udumm, &alpha_depth ); - if ( !use_cached || im->alt.mask_ximage == NULL || im->alt.mask_ximage->depth != alpha_depth ) - { - if( (xim = asimage2alpha_ximage (asv, im, (alpha_depth == 1) )) == NULL ) + if (!use_cached || im->alt.mask_ximage == NULL || im->alt.mask_ximage->depth != (int)alpha_depth) { + if( (xim = asimage2alpha_ximage (asv, im, (alpha_depth == 1) )) == NULL ) { show_error("cannot export image into alpha XImage."); return None ; } - }else - xim = im->alt.mask_ximage ; + } else + xim = im->alt.mask_ximage ; if (xim != NULL ) { res = put_ximage( asv, xim, d, gc, src_x, src_y, dest_x, dest_y, width, height ); @@ -722,6 +758,18 @@ asimage2alpha_drawable( ASVisual *asv, Drawable d, ASImage *im, GC gc, } return res; } +#else + (void)asv; + (void)d; + (void)im; + (void)gc; + (void)src_x; + (void)src_y; + (void)dest_x; + (void)dest_y; + (void)width; + (void)height; + (void)use_cached; // silence unused variable warning #endif return False ; } @@ -744,6 +792,12 @@ asimage2pixmap(ASVisual *asv, Window root, ASImage *im, GC gc, Bool use_cached) } return p; } +#else + (void)asv; + (void)root; + (void)im; + (void)gc; + (void)use_cached; // silence unused variable warning #endif return None ; } @@ -781,7 +835,13 @@ asimage2alpha(ASVisual *asv, Window root, ASImage *im, GC gc, Bool use_cached, B XDestroyImage (xim); return mask; #else - return None ; + (void)asv; + (void)root; + (void)im; + (void)gc; + (void)use_cached; + (void)bitmap; // silence unused variable warning + return None ; #endif } diff --git a/graf2d/asimage/src/libAfterImage/ximage.h b/graf2d/asimage/src/libAfterImage/ximage.h index b88d2e70e71bf..313f9d8d3c093 100644 --- a/graf2d/asimage/src/libAfterImage/ximage.h +++ b/graf2d/asimage/src/libAfterImage/ximage.h @@ -298,8 +298,6 @@ ASImage *pixmap2asimage (struct ASVisual *asv, Pixmap p, int x, int y, * asimage2pixmap() creates new pixmap of exactly same size as * supplied ASImage. It then calls asimage2drawable to copy entire content * of the ASImage onto that created pixmap. - * EXAMPLE - * asview.c: ASView.5 * SEE ALSO * asimage2ximage() * asimage2drawable() diff --git a/graf2d/asimage/src/libAfterImage/xpm.c b/graf2d/asimage/src/libAfterImage/xpm.c index 006e8e1d29053..43de59705698d 100644 --- a/graf2d/asimage/src/libAfterImage/xpm.c +++ b/graf2d/asimage/src/libAfterImage/xpm.c @@ -22,11 +22,8 @@ #undef DO_CLOCKING #ifdef _WIN32 -#include "win32/config.h" #include #define read _read -#else -#include "config.h" #endif #ifdef HAVE_XPM @@ -66,11 +63,7 @@ #endif #endif -#ifdef _WIN32 -# include "win32/afterbase.h" -#else -# include "afterbase.h" -#endif +#include "afterbase.h" #include "asimage.h" #include "ascmap.h" #include "xpm.h" @@ -333,29 +326,30 @@ static inline char get_xpm_char( ASXpmFile *xpm_file ) { #ifdef HAVE_LIBXPM - return '\0'; + (void)xpm_file; // silence unused variable warning + return '\0'; #else char c; if( xpm_file->curr_byte >= xpm_file->bytes_in ) { - if( xpm_file->bytes_in > AS_XPM_BUFFER_UNDO ) - { - register char* src = &(xpm_file->buffer[xpm_file->bytes_in-AS_XPM_BUFFER_UNDO]); + if (xpm_file->bytes_in > (size_t)AS_XPM_BUFFER_UNDO) { + register char* src = &(xpm_file->buffer[xpm_file->bytes_in-AS_XPM_BUFFER_UNDO]); register char* dst = &(xpm_file->buffer[0]); register int i; - for( i = 0 ; i < AS_XPM_BUFFER_UNDO ; i++ ) - dst[i] = src[i]; + for (i = 0; i < (int)AS_XPM_BUFFER_UNDO; i++) + dst[i] = src[i]; /* xpm_file->bytes_in = AS_XPM_BUFFER_UNDO+fread( &(xpm_file->buffer[AS_XPM_BUFFER_UNDO]), 1, AS_XPM_BUFFER_SIZE, xpm_file->fp );*/ - xpm_file->bytes_in = xpm_file->data ? AS_XPM_BUFFER_UNDO + strlen(*xpm_file->data) : - AS_XPM_BUFFER_UNDO+read( xpm_file->fd, &(xpm_file->buffer[AS_XPM_BUFFER_UNDO]), AS_XPM_BUFFER_SIZE ); - xpm_file->curr_byte = AS_XPM_BUFFER_UNDO ; - } - if( xpm_file->bytes_in <= AS_XPM_BUFFER_UNDO ) - { - xpm_file->parse_state = XPM_Outside ; + xpm_file->bytes_in = xpm_file->data + ? (size_t)AS_XPM_BUFFER_UNDO + strlen(*xpm_file->data) + : (size_t)AS_XPM_BUFFER_UNDO + + read(xpm_file->fd, &(xpm_file->buffer[AS_XPM_BUFFER_UNDO]), AS_XPM_BUFFER_SIZE); + xpm_file->curr_byte = (size_t)AS_XPM_BUFFER_UNDO; + } + if (xpm_file->bytes_in <= (size_t)AS_XPM_BUFFER_UNDO) { + xpm_file->parse_state = XPM_Outside ; return '\0'; - } - } + } + } c = xpm_file->buffer[xpm_file->curr_byte]; /* fprintf( stderr, "curr byte = %d ( of %d ), char = %c\n", xpm_file->curr_byte, xpm_file->bytes_in, c ); */ @@ -389,10 +383,11 @@ skip_xpm_comments( ASXpmFile *xpm_file ) { c = get_xpm_char(xpm_file); if( c == '*' ) - if( (c=get_xpm_char(xpm_file)) == '/' ) - xpm_file->parse_state--; - } - } + if (get_xpm_char(xpm_file) == '/') { + xpm_file->parse_state--; + } + } + } } static Bool @@ -769,8 +764,9 @@ lookup_xpm_color( char **colornames, ASHashTable *xpm_color_names ) void string_value_destroy (ASHashableValue value, void *data) { - if ((char*)value != NULL) - free ((char*)value); + (void)data; // silence unused variable warning + if ((char *)value != NULL) + free((char *)value); } Bool @@ -883,9 +879,10 @@ convert_xpm_scanline( ASXpmFile *xpm_file, unsigned int line ) #ifdef HAVE_LIBXPM unsigned int *data = xpm_file->xpmImage.data+k*line ; #else - unsigned char *data ; - if( get_xpm_string( xpm_file ) != XPM_Success) - return False ; + (void)line; // silence unused variable warning + unsigned char *data; + if (get_xpm_string(xpm_file) != XPM_Success) + return False ; data = (unsigned char*)xpm_file->str_buf ; #endif if( cmap ) diff --git a/graf2d/cocoa/CMakeLists.txt b/graf2d/cocoa/CMakeLists.txt index 3bdce5e3558a2..6ba704372e0a5 100644 --- a/graf2d/cocoa/CMakeLists.txt +++ b/graf2d/cocoa/CMakeLists.txt @@ -41,13 +41,11 @@ ROOT_STANDARD_LIBRARY_PACKAGE(GCocoa GQuartz ${COCOA_FRAMEWORK} ${OPENGL_FRAMEWORK} - ${FREETYPE_LIBRARIES} + Freetype::Freetype ) target_include_directories(GCocoa PRIVATE ${CMAKE_SOURCE_DIR}/graf3d/gl/inc) # We know GL is deprecated on macOS. And our answer is WebGUI/Graphics. target_compile_options(GCocoa PRIVATE -ObjC++ -Wno-deprecated-declarations) -target_include_directories(GCocoa PRIVATE ${FREETYPE_INCLUDE_DIRS}) - target_include_directories(GCocoa PRIVATE ${OPENGL_INCLUDE_DIR}) diff --git a/graf2d/cocoa/inc/QuartzPixmap.h b/graf2d/cocoa/inc/QuartzPixmap.h index dd6f3f526c413..46cc9ae4d51a8 100644 --- a/graf2d/cocoa/inc/QuartzPixmap.h +++ b/graf2d/cocoa/inc/QuartzPixmap.h @@ -41,6 +41,13 @@ ROOT::MacOSX::Util::CFScopeGuard fContext; CGFloat fScaleFactor; + + TAttLine fAttLine; ///< current line attributes + TAttFill fAttFill; ///< current fill attributes + TAttMarker fAttMarker; ///< current marker attribute + TAttText fAttText; ///< current text attribute + + BOOL fDirectDraw; } - (id) initWithW : (unsigned) width H : (unsigned) height scaleFactor : (CGFloat) scaleFactor; @@ -62,6 +69,16 @@ - (unsigned) fWidth; - (unsigned) fHeight; +//Graphical attributes +@property (nonatomic, readonly) TAttLine *attLine; +@property (nonatomic, readonly) TAttFill *attFill; +@property (nonatomic, readonly) TAttMarker *attMarker; +@property (nonatomic, readonly) TAttText *attText; + +- (void) setDirectDraw : (BOOL) mode; +- (BOOL) isDirectDraw; + + - (void) copy : (NSObject *) src area : (ROOT::MacOSX::X11::Rectangle) area withMask : (QuartzImage *) mask clipOrigin : (ROOT::MacOSX::X11::Point) origin toPoint : (ROOT::MacOSX::X11::Point) dstPoint; @@ -93,6 +110,11 @@ unsigned fWidth; unsigned fHeight; + TAttLine fAttLine; ///< current line attributes + TAttFill fAttFill; ///< current fill attributes + TAttMarker fAttMarker; ///< current marker attribute + TAttText fAttText; ///< current text attribute + ROOT::MacOSX::Util::CFScopeGuard fImage; std::vector fImageData; } @@ -118,6 +140,12 @@ - (unsigned char *) readColorBits : (ROOT::MacOSX::X11::Rectangle) area; +//Graphical attributes +@property (nonatomic, readonly) TAttLine *attLine; +@property (nonatomic, readonly) TAttFill *attFill; +@property (nonatomic, readonly) TAttMarker *attMarker; +@property (nonatomic, readonly) TAttText *attText; + @end diff --git a/graf2d/cocoa/inc/QuartzWindow.h b/graf2d/cocoa/inc/QuartzWindow.h index 7d7e6aba368d2..79c5c3c0d999e 100644 --- a/graf2d/cocoa/inc/QuartzWindow.h +++ b/graf2d/cocoa/inc/QuartzWindow.h @@ -42,7 +42,7 @@ class Command; // // //////////////////////////////////////////////////////////////////////// @interface XorDrawingView: NSView -- (void) setXorOperations : (const std::vector &) primitives; +- (void) addXorCommand : (ROOT::MacOSX::X11::Command *) cmd; @end // XorDrawingWindow is a special window: a transparent @@ -68,11 +68,12 @@ class Command; @private QuartzWindow *fMainWindow; BOOL fHasFocus; - + QuartzView *fContentView; BOOL fDelayedTransient; QuartzImage *fShapeCombineMask; BOOL fIsDeleted; + TVirtualX::EDrawMode fDrawMode; // current draw mode } - (id) initWithContentRect : (NSRect) contentRect styleMask : (NSUInteger) windowStyle @@ -127,11 +128,15 @@ class Command; - (unsigned char *) readColorBits : (ROOT::MacOSX::X11::Rectangle) area; // Trick for crosshair drawing in TCanvas ("pseudo-XOR") -- (void) addXorWindow; -- (void) adjustXorWindowGeometry; +- (XorDrawingWindow *) addXorWindow; +- (XorDrawingWindow *) findXorWindow; - (void) adjustXorWindowGeometry : (XorDrawingWindow *) win; - (void) removeXorWindow; -- (XorDrawingWindow *) findXorWindow; +- (void) addXorLine : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2; +- (void) addXorBox : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2; +- (void) setDrawMode : (TVirtualX::EDrawMode) newMode; +- (TVirtualX::EDrawMode) getDrawMode; + //X11Window protocol. @@ -203,6 +208,13 @@ class Command; unsigned long fBackgroundPixel; BOOL fOverrideRedirect; + TAttLine fAttLine; ///< current line attributes + TAttFill fAttFill; ///< current fill attributes + TAttMarker fAttMarker; ///< current marker attribute + TAttText fAttText; ///< current text attribute + + BOOL fDirectDraw; + BOOL fHasFocus; QuartzView *fParentView; @@ -238,6 +250,18 @@ class Command; - (BOOL) fIsOpenGLWidget; - (CGFloat) fScaleFactor; +//Graphical attributes +@property (nonatomic, readonly) TAttLine *attLine; +@property (nonatomic, readonly) TAttFill *attFill; +@property (nonatomic, readonly) TAttMarker *attMarker; +@property (nonatomic, readonly) TAttText *attText; + +- (void) setDrawMode : (TVirtualX::EDrawMode) newMode; +- (TVirtualX::EDrawMode) getDrawMode; + +- (void) setDirectDraw : (BOOL) mode; +- (BOOL) isDirectDraw; + @property (nonatomic, assign) CGContextRef fContext; //Geometry. diff --git a/graf2d/cocoa/inc/TGCocoa.h b/graf2d/cocoa/inc/TGCocoa.h index 0ec9a188991c5..28f67306a3386 100644 --- a/graf2d/cocoa/inc/TGCocoa.h +++ b/graf2d/cocoa/inc/TGCocoa.h @@ -103,6 +103,13 @@ class TGCocoa : public TVirtualX { Int_t AddWindow(ULong_t qwid, UInt_t w, UInt_t h) override; //-"Qt ROOT". void RemoveWindow(ULong_t qwid) override; //-"Qt ROOT". + //---- Methods used for new graphics ----- + WinContext_t GetWindowContext(Int_t wid) override; + WinContext_t GetSelectedContext(); + void SetDrawModeW(WinContext_t wctxt, EDrawMode mode) override; + EDrawMode GetDrawModeW(WinContext_t wctxt) override; + void ClearWindowW(WinContext_t wctxt) override; + void UpdateWindowW(WinContext_t wctxt, Int_t mode) override; //-Functions used by GUI. Window_t CreateWindow(Window_t parent, Int_t x, Int_t y, diff --git a/graf2d/cocoa/inc/TGQuartz.h b/graf2d/cocoa/inc/TGQuartz.h index 25ca55bdd6276..8c9e8603c557c 100644 --- a/graf2d/cocoa/inc/TGQuartz.h +++ b/graf2d/cocoa/inc/TGQuartz.h @@ -27,9 +27,6 @@ MacOS X, using CoreGraphics (Quartz). class TGQuartz : public TGCocoa { private: - enum EAlign {kNone, kTLeft, kTCenter, kTRight, kMLeft, - kMCenter, kMRight, kBLeft, kBCenter, kBRight}; - FT_Vector fAlign; // alignment vector public: TGQuartz(); @@ -78,6 +75,22 @@ class TGQuartz : public TGCocoa { Int_t GetFontDescent(const char *text) const override; Float_t GetTextMagnitude() override; + //---- Methods used for new graphics ----- + void SetAttFill(WinContext_t wctxt, const TAttFill &att) override; + void SetAttLine(WinContext_t wctxt, const TAttLine &att) override; + void SetAttMarker(WinContext_t wctxt, const TAttMarker &att) override; + void SetAttText(WinContext_t wctxt, const TAttText &att) override; + + void DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) override; + void DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2) override; + void DrawPolyLineW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; + void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode) override; + + private: //Unfortunately, I have to convert from @@ -93,13 +106,17 @@ class TGQuartz : public TGCocoa { bool fUseAA; bool fUseFAAA; - void AlignTTFString(); - Bool_t IsTTFStringVisible(Int_t x, Int_t y, UInt_t w, UInt_t h); - void RenderTTFString(Int_t x, Int_t y, ETextMode mode); + void AlignTTFString(WinContext_t wctxt); + Bool_t IsTTFStringVisible(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h); + void RenderTTFString(WinContext_t wctxt, Int_t x, Int_t y, ETextMode mode); void DrawFTGlyphIntoPixmap(void *pixmap, FT_Bitmap *source, ULong_t fore, ULong_t back, Int_t bx, Int_t by); void SetAA(); - void *GetSelectedDrawableChecked(const char *calledFrom) const; + TAttFill &GetAttFill(WinContext_t wctxt); + TAttLine &GetAttLine(WinContext_t wctxt); + TAttMarker &GetAttMarker(WinContext_t wctxt); + TAttText &GetAttText(WinContext_t wctxt); + void *GetPixmapDrawable(void *drawable0, const char *calledFrom) const; TGQuartz(const TGQuartz &rhs); TGQuartz &operator = (const TGQuartz &rhs); diff --git a/graf2d/cocoa/inc/X11Buffer.h b/graf2d/cocoa/inc/X11Buffer.h index 635a017102083..75c52cc3b7bde 100644 --- a/graf2d/cocoa/inc/X11Buffer.h +++ b/graf2d/cocoa/inc/X11Buffer.h @@ -245,8 +245,6 @@ class CommandBuffer { std::vector fCommands; std::vector fViewBranch; - - std::vector fXorOps; public: typedef std::vector::size_type size_type; @@ -264,22 +262,15 @@ class CommandBuffer { void AddUpdateWindow(QuartzView *view); void AddDeletePixmap(Pixmap_t pixmap); - //'XOR' graphics for canvas. - void AddDrawBoxXor(Window_t windowID, Int_t x1, Int_t y1, Int_t x2, Int_t y2); - void AddDrawLineXor(Window_t windowID, Int_t x1, Int_t y1, Int_t x2, Int_t y2); - void Flush(Details::CocoaPrivate *impl); - void FlushXOROps(Details::CocoaPrivate *impl); void RemoveOperationsForDrawable(Drawable_t wid); void RemoveGraphicsOperationsForWindow(Window_t wid); - void RemoveXORGraphicsOperationsForWindow(Window_t wid); size_type BufferSize()const { return fCommands.size(); } - void ClearXOROperations(); private: void ClearCommands(); //Clip related stuff. diff --git a/graf2d/cocoa/inc/X11Drawable.h b/graf2d/cocoa/inc/X11Drawable.h index ee969ef271033..63997bea1f94f 100644 --- a/graf2d/cocoa/inc/X11Drawable.h +++ b/graf2d/cocoa/inc/X11Drawable.h @@ -53,6 +53,18 @@ - (unsigned) fWidth; - (unsigned) fHeight; +//Graphical attributes +@property (nonatomic, readonly) TAttLine *attLine; +@property (nonatomic, readonly) TAttFill *attFill; +@property (nonatomic, readonly) TAttMarker *attMarker; +@property (nonatomic, readonly) TAttText *attText; + +// new graphics methods +- (void) setDrawMode : (TVirtualX::EDrawMode) newMode; +- (TVirtualX::EDrawMode) getDrawMode; +- (void) setDirectDraw : (BOOL) mode; +- (BOOL) isDirectDraw; + //Functions to copy one drawable into another. - (void) copy : (NSObject *) src area : (ROOT::MacOSX::X11::Rectangle) area withMask : (QuartzImage *)mask clipOrigin : (ROOT::MacOSX::X11::Point) origin toPoint : (ROOT::MacOSX::X11::Point) dstPoint; diff --git a/graf2d/cocoa/src/QuartzPixmap.mm b/graf2d/cocoa/src/QuartzPixmap.mm index ce26cb7df1642..91e756e14e7c1 100644 --- a/graf2d/cocoa/src/QuartzPixmap.mm +++ b/graf2d/cocoa/src/QuartzPixmap.mm @@ -39,6 +39,7 @@ - (id) initWithW : (unsigned) width H : (unsigned) height scaleFactor : (CGFloat if (self = [super init]) { fWidth = 0; fHeight = 0; + fDirectDraw = NO; if (![self resizeW : width H : height scaleFactor : scaleFactor]) { [self release]; @@ -187,6 +188,42 @@ - (unsigned) fHeight return fHeight; } +//______________________________________________________________________________ +- (TAttLine *) attLine +{ + return &fAttLine; +} + +//______________________________________________________________________________ +- (TAttFill *) attFill +{ + return &fAttFill; +} + +//______________________________________________________________________________ +- (TAttMarker *) attMarker +{ + return &fAttMarker; +} + +//______________________________________________________________________________ +- (TAttText *) attText +{ + return &fAttText; +} + +//______________________________________________________________________________ +- (void) setDirectDraw : (BOOL) mode +{ + fDirectDraw = mode; +} + +//______________________________________________________________________________ +- (BOOL) isDirectDraw +{ + return fDirectDraw; +} + //______________________________________________________________________________ - (void) copyImage : (QuartzImage *) srcImage area : (X11::Rectangle) area withMask : (QuartzImage *) mask clipOrigin : (X11::Point) clipXY toPoint : (X11::Point) dstPoint @@ -410,6 +447,7 @@ - (void) addPixel : (const unsigned char *) rgb @end + @implementation QuartzImage @synthesize fIsStippleMask; @@ -758,6 +796,30 @@ - (unsigned) fHeight return fHeight; } +//______________________________________________________________________________ +- (TAttLine *) attLine +{ + return &fAttLine; +} + +//______________________________________________________________________________ +- (TAttFill *) attFill +{ + return &fAttFill; +} + +//______________________________________________________________________________ +- (TAttMarker *) attMarker +{ + return &fAttMarker; +} + +//______________________________________________________________________________ +- (TAttText *) attText +{ + return &fAttText; +} + //______________________________________________________________________________ - (CGImageRef) fImage { diff --git a/graf2d/cocoa/src/QuartzWindow.mm b/graf2d/cocoa/src/QuartzWindow.mm index 7a137011bc9aa..46a260a6fde8e 100644 --- a/graf2d/cocoa/src/QuartzWindow.mm +++ b/graf2d/cocoa/src/QuartzWindow.mm @@ -1127,9 +1127,9 @@ @implementation XorDrawingView std::vector xorOps; } -- (void) setXorOperations : (const std::vector &) primitives +- (void) addXorCommand : (ROOT::MacOSX::X11::Command *) cmd { - xorOps = primitives; + xorOps.push_back(cmd); } - (void) drawRect : (NSRect) dirtyRect @@ -1224,6 +1224,7 @@ - (id) initWithContentRect : (NSRect) contentRect styleMask : (NSUInteger) windo fIsDeleted = NO; fHasFocus = NO; + fDrawMode = TVirtualX::kCopy; } return self; @@ -1254,6 +1255,7 @@ - (id) initWithGLView : (ROOTOpenGLView *) glView fDelayedTransient = NO; fIsDeleted = NO; fHasFocus = NO; + fDrawMode = TVirtualX::kCopy; } return self; @@ -1506,22 +1508,18 @@ - (unsigned char *) readColorBits : (X11::Rectangle) area #pragma mark - XorDrawinWindow/View //______________________________________________________________________________ -- (void) addXorWindow +- (XorDrawingWindow *) addXorWindow { - if ([self findXorWindow]) - return; - - XorDrawingWindow *special = [[XorDrawingWindow alloc] init]; - [self adjustXorWindowGeometry:special]; - [self addChildWindow : special ordered : NSWindowAbove]; - [special release]; -} + auto res = [self findXorWindow]; + if (res) + return res; -//______________________________________________________________________________ -- (void) adjustXorWindowGeometry -{ - if (auto win = [self findXorWindow]) - [self adjustXorWindowGeometry:win]; + XorDrawingWindow *special = [[XorDrawingWindow alloc] init]; + res = special; + [self adjustXorWindowGeometry : special]; + [self addChildWindow : special ordered : NSWindowAbove]; + [special release]; + return res; } //______________________________________________________________________________ @@ -1536,12 +1534,12 @@ - (void) adjustXorWindowGeometry : (XorDrawingWindow *) win //______________________________________________________________________________ - (void) removeXorWindow { - if (auto win = [self findXorWindow]) { - // For some reason, without ordeing out, the crosshair window's content stays - // in the parent's window. Thus we first have to order out the crosshair window. - [win orderOut:nil]; - [self removeChildWindow : win]; - } + if (auto win = [self findXorWindow]) { + // For some reason, without ordeing out, the crosshair window's content stays + // in the parent's window. Thus we first have to order out the crosshair window. + [win orderOut:nil]; + [self removeChildWindow : win]; + } } //______________________________________________________________________________ @@ -1555,6 +1553,59 @@ - (XorDrawingWindow *) findXorWindow return nil; } +//______________________________________________________________________________ +- (void) addXorLine : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2 +{ + auto xorWindow = [self addXorWindow]; + + try { + std::unique_ptr cmd(new ROOT::MacOSX::X11::DrawLineXor(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2))); + cmd->setView(view); + + auto cv = (XorDrawingView *)xorWindow.contentView; + [cv addXorCommand : cmd.get()]; + cmd.release(); + [cv setNeedsDisplay : YES]; + + } catch (const std::exception &) { + throw; + } +} + +//______________________________________________________________________________ +- (void) addXorBox : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2 +{ + auto xorWindow = [self addXorWindow]; + + try { + std::unique_ptr cmd(new ROOT::MacOSX::X11::DrawBoxXor(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2))); + cmd->setView(view); + + auto cv = (XorDrawingView *)xorWindow.contentView; + [cv addXorCommand : cmd.get()]; + cmd.release(); + [cv setNeedsDisplay : YES]; + } catch (const std::exception &) { + throw; + } +} + + +//______________________________________________________________________________ +- (void) setDrawMode : (TVirtualX::EDrawMode) newMode +{ + if (fDrawMode == TVirtualX::kInvert && newMode != TVirtualX::kInvert) + [self removeXorWindow]; + + fDrawMode = newMode; +} + +//______________________________________________________________________________ +- (TVirtualX::EDrawMode) getDrawMode +{ + return fDrawMode; +} + #pragma mark - X11Window protocol's implementation. @@ -1982,6 +2033,8 @@ - (id) initWithFrame : (NSRect) frame windowAttributes : (const SetWindowAttribu fBackBuffer = nil; fID = 0; + fDirectDraw = NO; + //Passive grab parameters. fPassiveGrabButton = -1;//0 is kAnyButton. fPassiveGrabEventMask = 0; @@ -2123,6 +2176,58 @@ - (void) setDrawableSize : (NSSize) newSize self.frame = frame; } +//______________________________________________________________________________ +- (TAttLine *) attLine +{ + return &fAttLine; +} + +//______________________________________________________________________________ +- (TAttFill *) attFill +{ + return &fAttFill; +} + +//______________________________________________________________________________ +- (TAttMarker *) attMarker +{ + return &fAttMarker; +} + +//______________________________________________________________________________ +- (TAttText *) attText +{ + return &fAttText; +} + +//______________________________________________________________________________ +- (void) setDrawMode : (TVirtualX::EDrawMode) newMode +{ + [self.fQuartzWindow setDrawMode:newMode]; +} + +//______________________________________________________________________________ +- (TVirtualX::EDrawMode) getDrawMode +{ + return [self.fQuartzWindow getDrawMode]; +} + +//______________________________________________________________________________ +- (void) setDirectDraw : (BOOL) mode +{ + fDirectDraw = mode; + + // while painting operates with the pixmap, set direct flag for it too + if (fBackBuffer) + [fBackBuffer setDirectDraw : mode]; +} + +//______________________________________________________________________________ +- (BOOL) isDirectDraw +{ + return fDirectDraw; +} + //______________________________________________________________________________ - (void) setX : (int) x Y : (int) y width : (unsigned) w height : (unsigned) h { diff --git a/graf2d/cocoa/src/TGCocoa.mm b/graf2d/cocoa/src/TGCocoa.mm index ca61ca61b694a..004ea9586eabe 100644 --- a/graf2d/cocoa/src/TGCocoa.mm +++ b/graf2d/cocoa/src/TGCocoa.mm @@ -585,8 +585,12 @@ void FixAscii(std::vector &text) fPimpl->fX11CommandBuffer.Flush(fPimpl.get()); } - if (fDirectDraw && mode != 2) - fPimpl->fX11CommandBuffer.FlushXOROps(fPimpl.get()); + if (fDirectDraw && mode != 2) { + // here was flushing of XOR operation + // now XOR operations collected directly by correspondent view and + // updated asynchronousely by calling view.setNeedsDisplay(YES) + // so there is no need for central instance + } } //______________________________________________________________________________ @@ -676,13 +680,42 @@ void FixAscii(std::vector &text) } //______________________________________________________________________________ -void TGCocoa::ClearWindow() +WinContext_t TGCocoa::GetWindowContext(Int_t wid) { - //Clear the selected drawable OR pixmap (the name - from TVirtualX interface - is bad). - assert(fSelectedDrawable > fPimpl->GetRootWindowID() && - "ClearWindow, fSelectedDrawable is invalid"); + if (!wid) + return (WinContext_t) 0; + auto drawable = fPimpl->GetDrawable(wid); + return (WinContext_t) drawable; +} + +//______________________________________________________________________________ +WinContext_t TGCocoa::GetSelectedContext() +{ + return GetWindowContext(fSelectedDrawable); +} + +//______________________________________________________________________________ +void TGCocoa::SetDrawModeW(WinContext_t wctxt, EDrawMode mode) +{ + auto drawable = (NSObject *) wctxt; + + // here XOR window and XOR operations can be removed if necessary + [drawable setDrawMode : mode]; +} + +//______________________________________________________________________________ +TVirtualX::EDrawMode TGCocoa::GetDrawModeW(WinContext_t wctxt) +{ + auto drawable = (NSObject *) wctxt; + + return [drawable getDrawMode]; +} + +//______________________________________________________________________________ +void TGCocoa::ClearWindowW(WinContext_t wctxt) +{ + auto drawable = (NSObject * const) wctxt; - NSObject * const drawable = fPimpl->GetDrawable(fSelectedDrawable); if (drawable.fIsPixmap) { //Pixmaps are white by default. //This is bad - we can not have transparent sub-pads (in TCanvas) @@ -697,10 +730,50 @@ void FixAscii(std::vector &text) CGContextClearRect(pixmapCtx, CGRectMake(0, 0, drawable.fWidth, drawable.fHeight)); } else { //For a window ClearArea with w == 0 and h == 0 means the whole window. - ClearArea(fSelectedDrawable, 0, 0, 0, 0); + ClearArea(drawable.fID, 0, 0, 0, 0); } } +//______________________________________________________________________________ +void TGCocoa::UpdateWindowW(WinContext_t wctxt, Int_t /* mode */) +{ + auto window = (NSObject * const) wctxt; + + //Have no idea, why this can happen with ROOT - done by TGDNDManager :( + if (window.fIsPixmap == YES) + return; + + if (QuartzPixmap * const pixmap = window.fBackBuffer) { + assert([window.fContentView isKindOfClass : [QuartzView class]] && "UpdateWindow, content view is not a QuartzView"); + QuartzView *dstView = (QuartzView *)window.fContentView; + + if (dstView.fIsOverlapped) + return; + + if (dstView.fContext) { + //We can draw directly. + const X11::Rectangle copyArea(0, 0, pixmap.fWidth, pixmap.fHeight); + [dstView copy : pixmap area : copyArea withMask : nil clipOrigin : X11::Point() toPoint : X11::Point()]; + } else { + //Have to wait. + fPimpl->fX11CommandBuffer.AddUpdateWindow(dstView); + Update(1); + } + } +} + + + +//______________________________________________________________________________ +void TGCocoa::ClearWindow() +{ + //Clear the selected drawable OR pixmap (the name - from TVirtualX interface - is bad). + assert(fSelectedDrawable > fPimpl->GetRootWindowID() && + "ClearWindow, fSelectedDrawable is invalid"); + + ClearWindowW((WinContext_t)fPimpl->GetDrawable(fSelectedDrawable)); +} + //______________________________________________________________________________ void TGCocoa::GetGeometry(Int_t windowID, Int_t & x, Int_t &y, UInt_t &w, UInt_t &h) { @@ -789,7 +862,7 @@ void FixAscii(std::vector &text) } //______________________________________________________________________________ -void TGCocoa::UpdateWindow(Int_t /*mode*/) +void TGCocoa::UpdateWindow(Int_t mode) { //This function is used by TCanvas/TPad: //draw "back buffer" image into the view. @@ -806,25 +879,7 @@ void FixAscii(std::vector &text) if (fPimpl->GetDrawable(fSelectedDrawable).fIsPixmap == YES) return; - NSObject * const window = fPimpl->GetWindow(fSelectedDrawable); - - if (QuartzPixmap * const pixmap = window.fBackBuffer) { - assert([window.fContentView isKindOfClass : [QuartzView class]] && "UpdateWindow, content view is not a QuartzView"); - QuartzView *dstView = (QuartzView *)window.fContentView; - - if (dstView.fIsOverlapped) - return; - - if (dstView.fContext) { - //We can draw directly. - const X11::Rectangle copyArea(0, 0, pixmap.fWidth, pixmap.fHeight); - [dstView copy : pixmap area : copyArea withMask : nil clipOrigin : X11::Point() toPoint : X11::Point()]; - } else { - //Have to wait. - fPimpl->fX11CommandBuffer.AddUpdateWindow(dstView); - Update(1); - } - } + UpdateWindowW((WinContext_t) fPimpl->GetWindow(fSelectedDrawable), mode); } //______________________________________________________________________________ @@ -3454,6 +3509,17 @@ void FixAscii(std::vector &text) void TGCocoa::SetDoubleBufferOFF() { fDirectDraw = true; + + assert(fSelectedDrawable > fPimpl->GetRootWindowID() && + "SetDoubleBufferON, called, but no correct window was selected before"); + + NSObject * const window = fPimpl->GetWindow(fSelectedDrawable); + if (!window) return; + + assert(window.fIsPixmap == NO && + "SetDoubleBufferON, selected drawable is a pixmap, can not attach pixmap to pixmap"); + + [window setDirectDraw : YES]; } //______________________________________________________________________________ @@ -3466,12 +3532,13 @@ void FixAscii(std::vector &text) "SetDoubleBufferON, called, but no correct window was selected before"); NSObject * const window = fPimpl->GetWindow(fSelectedDrawable); - if (!window) return; assert(window.fIsPixmap == NO && "SetDoubleBufferON, selected drawable is a pixmap, can not attach pixmap to pixmap"); + [window setDirectDraw : NO]; + const unsigned currW = window.fWidth; const unsigned currH = window.fHeight; @@ -3492,17 +3559,12 @@ void FixAscii(std::vector &text) //______________________________________________________________________________ void TGCocoa::SetDrawMode(EDrawMode mode) { - // Sets the drawing mode. + // Sets the drawing mode for all windows. // - //EDrawMode{kCopy, kXor, kInvert}; - if (fDrawMode == kInvert && mode != kInvert) { - // Remove previously added CrosshairWindow. - auto windows = NSApplication.sharedApplication.windows; - for (NSWindow *candidate : windows) { - if ([candidate isKindOfClass:QuartzWindow.class]) - [(QuartzWindow *)candidate removeXorWindow]; - } - fPimpl->fX11CommandBuffer.ClearXOROperations(); + auto windows = NSApplication.sharedApplication.windows; + for (NSWindow *candidate : windows) { + if ([candidate isKindOfClass:QuartzWindow.class]) + [(QuartzWindow *)candidate setDrawMode : mode]; } fDrawMode = mode; diff --git a/graf2d/cocoa/src/TGQuartz.mm b/graf2d/cocoa/src/TGQuartz.mm index 72cbf2dd97017..fab43c8649a02 100644 --- a/graf2d/cocoa/src/TGQuartz.mm +++ b/graf2d/cocoa/src/TGQuartz.mm @@ -113,27 +113,31 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const) wctxt; + if (!drawable0) + return; + //Check some conditions first. - if (fDirectDraw) { - if (!fPimpl->GetDrawable(fSelectedDrawable).fIsPixmap) { - QuartzView * const view = (QuartzView *)fPimpl->GetWindow(fSelectedDrawable).fContentView; + if ([drawable0 isDirectDraw]) { + if (!drawable0.fIsPixmap) { + QuartzView * const view = (QuartzView *)fPimpl->GetWindow(drawable0.fID).fContentView; if (!view) { - ::Warning("DrawLine", "Invalid view/window for XOR-mode"); + ::Warning("DrawBoxW", "Invalid view/window for XOR-mode"); return; } - if (![view.fQuartzWindow findXorWindow]) - [view.fQuartzWindow addXorWindow]; - fPimpl->fX11CommandBuffer.AddDrawBoxXor(fSelectedDrawable, x1, y1, x2, y2); + [view.fQuartzWindow addXorBox: view : x1 : y1 : x2 : y2]; } return; } - NSObject * const drawable = (NSObject *)GetSelectedDrawableChecked("DrawBox"); + auto &attline = GetAttLine(wctxt); + auto &attfill = GetAttFill(wctxt); + + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawBoxW"); if (!drawable) return; @@ -146,7 +150,7 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector(gROOT->GetColor(GetFillColor()))) { + if (const TColorGradient * const gradient = dynamic_cast(gROOT->GetColor(attfill.GetFillColor()))) { //Draw a box with a gradient fill and a shadow. //Ignore all fill styles and EBoxMode, use a gradient fill. TPoint polygon[4]; @@ -158,31 +162,37 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const) wctxt; + if (!drawable0) return; - //Do some checks first. - if (fDirectDraw)//To avoid warnings from Quartz - no context at the moment! + if (n < 3) + return; + // No fill area with direct drawing + if ([drawable0 isDirectDraw]) return; - NSObject * const drawable = - (NSObject *)GetSelectedDrawableChecked("DrawFillArea"); + auto &attfill = GetAttFill(wctxt); + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawFillAreaW"); if (!drawable) return; @@ -218,9 +230,9 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorGetColor(GetFillColor()); + const TColor * const fillColor = gROOT->GetColor(attfill.GetFillColor()); if (!fillColor) { - Error("DrawFillArea", "Could not find TColor for index %d", GetFillColor()); + Error("DrawFillAreaW", "Could not find TColor for index %d", attfill.GetFillColor()); return; } @@ -229,16 +241,25 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const) wctxt; + if (!drawable0) + return; - if (fDirectDraw) { - if (!fPimpl->GetDrawable(fSelectedDrawable).fIsPixmap) { - QuartzView * const view = (QuartzView *)fPimpl->GetWindow(fSelectedDrawable).fContentView; + if ([drawable0 isDirectDraw]) { + if (!drawable0.fIsPixmap) { + QuartzView * const view = (QuartzView *)fPimpl->GetWindow(drawable0.fID).fContentView; if (!view) { - ::Warning("DrawLine", "Invalid view/window for XOR-mode"); + ::Warning("DrawLineW", "Invalid view/window for XOR-mode"); return; } - if (![view.fQuartzWindow findXorWindow]) - [view.fQuartzWindow addXorWindow]; - fPimpl->fX11CommandBuffer.AddDrawLineXor(fSelectedDrawable, x1, y1, x2, y2); + [view.fQuartzWindow addXorLine: view : x1 : y1 : x2 : y2]; } return; } - //Do some checks first: - assert(fSelectedDrawable > fPimpl->GetRootWindowID() && "DrawLine, bad drawable is selected"); - NSObject * const drawable = - (NSObject *)GetSelectedDrawableChecked("DrawLine"); + auto &attline = GetAttLine(wctxt); + + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawLineW"); if (!drawable) return; @@ -282,34 +299,45 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector fPimpl->GetRootWindowID() && "DrawLine, bad drawable is selected"); + + DrawLineW(GetSelectedContext(), x1, y1, x2, y2); +} + //______________________________________________________________________________ -void TGQuartz::DrawPolyLine(Int_t n, TPoint *xy) +void TGQuartz::DrawPolyLineW(WinContext_t wctxt, Int_t n, TPoint *xy) { - //Comment from TVirtualX: - // Draw a line through all points. - // n : number of points - // xy : list of points - //End of comment. + auto drawable0 = (NSObject * const) wctxt; + if (!drawable0) + return; //Some checks first. - if (fDirectDraw)//To avoid warnings from Quartz - no context at the moment! + if ([drawable0 isDirectDraw]) return; - NSObject * const drawable = - (NSObject *)GetSelectedDrawableChecked("DrawPolyLine"); + auto &attline = GetAttLine(wctxt); + + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawPolyLineW"); if (!drawable) return; @@ -318,13 +346,13 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector fPimpl->GetRootWindowID() && "DrawPolyLine, bad drawable is selected"); + + DrawPolyLineW(GetSelectedContext(), n, xy); +} + +//______________________________________________________________________________ +void TGQuartz::DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xy) +{ + for(Int_t i = 0; i < 2*n; i += 2) + DrawPolyLineW(wctxt, 2, &xy[i]); +} + +//______________________________________________________________________________ +void TGQuartz::DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xy) +{ + auto drawable0 = (NSObject * const) wctxt; + if (!drawable0) + return; + //Do some checks first. - if (fDirectDraw)//To avoid warnings from Quartz - no context at the moment! + if ([drawable0 isDirectDraw]) return; - NSObject * const drawable = - (NSObject *)GetSelectedDrawableChecked("DrawPolyMarker"); + auto &attmark = GetAttMarker(wctxt); + + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawPolyMarkerW"); if (!drawable) return; @@ -361,21 +408,21 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector 1.) CGContextScaleCTM(ctx, 1. / drawable.fScaleFactor, 1. / drawable.fScaleFactor); - Style_t markerstyle = TAttMarker::GetMarkerStyleBase(GetMarkerStyle()); + Style_t markerstyle = TAttMarker::GetMarkerStyleBase(attmark.GetMarkerStyle()); // The fast pixel markers need to be treated separately if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) { @@ -386,29 +433,46 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const) wctxt; + if (!drawable0) + return; + + if ([drawable0 isDirectDraw]) return; if (!text || !text[0])//Can this ever happen? TPad::PaintText does not check this. return; - if (GetTextSize()<1.5)//Do not draw anything, or CoreText will create some small (but not of size 0 font). + auto &atttext = GetAttText(wctxt); + + if (atttext.GetTextSize() < 1.5)//Do not draw anything, or CoreText will create some small (but not of size 0 font). return; - NSObject * const drawable = - (NSObject *)GetSelectedDrawableChecked("DrawText"); + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawTextW"); if (!drawable) return; @@ -419,8 +483,8 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorfFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) { - const unsigned fontIndex = GetTextFont() / 10; + if (CTFontRef currentFont = fPimpl->fFontManager.SelectFont(atttext.GetTextFont(), kScale * atttext.GetTextSize())) { + const unsigned fontIndex = atttext.GetTextFont() / 10; if (fontIndex == 12 || fontIndex == 15) {//Greek and math symbols. //This is a hack. Correct way is to extract glyphs from symbol.ttf, //find correct mapping, place this glyphs. This requires manual layout though (?), @@ -433,44 +497,51 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const) wctxt; + UInt_t width = 0; UInt_t height = 0; Int_t xy = 0; - GetWindowSize(GetCurrentWindow(), xy, xy, width, height); + GetWindowSize((Drawable_t) drawable.fID, xy, xy, width, height); // If string falls outside window, there is probably no need to draw it. if (x + int(w) <= 0 || x >= int(width)) @@ -808,7 +944,7 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const drawable = (NSObject *)GetSelectedDrawableChecked("DrawText"); + auto drawable0 = (NSObject * const) wctxt; + if (!drawable0) + return; + + if ([drawable0 isDirectDraw]) + return; + + auto &atttext = GetAttText(wctxt); + + if (!atttext.GetTextSize())//Do not draw anything, or CoreText will create some small (but not of size 0 font). + return; + + auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "RenderTTFString"); if (!drawable) return; @@ -829,7 +977,7 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector pixmap([[QuartzPixmap alloc] initWithW : w H : h scaleFactor : 1.f]); if (!pixmap.Get()) { - Error("DrawText", "pixmap creation failed"); + Error("RenderTTFString", "pixmap creation failed"); return; } @@ -867,7 +1015,7 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorleft + xOff; const Int_t by = h - bitmap->top - yOff; - DrawFTGlyphIntoPixmap(pixmap.Get(), source, TGCocoa::GetPixel(GetTextColor()), + DrawFTGlyphIntoPixmap(pixmap.Get(), source, TGCocoa::GetPixel(atttext.GetTextColor()), mode == kClear ? ULong_t(-1) : 0xffffff, bx, by); } @@ -1060,31 +1208,73 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector fPimpl->GetRootWindowID() && "GetSelectedDrawableChecked, bad drawable is selected"); + // attributes stored in direct drawable (view) and not in underlying pixmap + auto drawable = (NSObject *) wctxt; + if (!drawable || !drawable.attFill) + return *this; + return *drawable.attFill; +} - NSObject *drawable = fPimpl->GetDrawable(fSelectedDrawable); +//______________________________________________________________________________ +TAttLine &TGQuartz::GetAttLine(WinContext_t wctxt) +{ + // attributes stored in direct drawable (view) and not in underlying pixmap + auto drawable = (NSObject *) wctxt; + if (!drawable || !drawable.attLine) + return *this; + return *drawable.attLine; +} + +//______________________________________________________________________________ +TAttMarker &TGQuartz::GetAttMarker(WinContext_t wctxt) +{ + // attributes stored in direct drawable (view) and not in underlying pixmap + auto drawable = (NSObject *) wctxt; + if (!drawable || !drawable.attMarker) + return *this; + return *drawable.attMarker; +} + +//______________________________________________________________________________ +TAttText &TGQuartz::GetAttText(WinContext_t wctxt) +{ + // attributes stored in direct drawable (view) and not in underlying pixmap + auto drawable = (NSObject *) wctxt; + if (!drawable || !drawable.attText) + return *this; + return *drawable.attText; +} + +//______________________________________________________________________________ +void *TGQuartz::GetPixmapDrawable(void *drawable0, const char *calledFrom) const +{ + assert(calledFrom != 0 && "GetDrawableChecked, calledFrom parameter is null"); + + if (!drawable0) + return nullptr; + + auto drawable = (NSObject *) drawable0; if (!drawable.fIsPixmap) { //TPad/TCanvas ALWAYS draw only into a pixmap. if ([drawable isKindOfClass : [QuartzView class]]) { QuartzView *view = (QuartzView *)drawable; if (!view.fBackBuffer) { Error(calledFrom, "Selected window is not double buffered"); - return 0; + return nullptr; } drawable = view.fBackBuffer; } else { Error(calledFrom, "Selected drawable is neither a pixmap, nor a double buffered window"); - return 0; + return nullptr; } } if (!drawable.fContext) { Error(calledFrom, "Context is null"); - return 0; + return nullptr; } return drawable; diff --git a/graf2d/cocoa/src/X11Buffer.mm b/graf2d/cocoa/src/X11Buffer.mm index 77a91211f9f50..76cc0ed250f1e 100644 --- a/graf2d/cocoa/src/X11Buffer.mm +++ b/graf2d/cocoa/src/X11Buffer.mm @@ -335,7 +335,6 @@ CommandBuffer::~CommandBuffer() { ClearCommands(); - ClearXOROperations(); } //______________________________________________________________________________ @@ -499,30 +498,6 @@ } } -//______________________________________________________________________________ -void CommandBuffer::AddDrawBoxXor(Window_t windowID, Int_t x1, Int_t y1, Int_t x2, Int_t y2) -{ - try { - std::unique_ptr cmd(new DrawBoxXor(windowID, Point(x1, y1), Point(x2, y2))); - fXorOps.push_back(cmd.get()); - cmd.release(); - } catch (const std::exception &) { - throw; - } -} - -//______________________________________________________________________________ -void CommandBuffer::AddDrawLineXor(Window_t windowID, Int_t x1, Int_t y1, Int_t x2, Int_t y2) -{ - try { - std::unique_ptr cmd(new DrawLineXor(windowID, Point(x1, y1), Point(x2, y2))); - fXorOps.push_back(cmd.get()); - cmd.release(); - } catch (const std::exception &) { - throw; - } -} - //______________________________________________________________________________ void CommandBuffer::Flush(Details::CocoaPrivate *impl) { @@ -605,42 +580,6 @@ ClearCommands(); } -//______________________________________________________________________________ -void CommandBuffer::FlushXOROps(Details::CocoaPrivate *impl) -{ - // The only XOR operations we ever had to support were the drawing - // of lines for a crosshair in a TCanvas and drawing the histogram's - // range when using a fit panel/interactive fitting. In the past - // we were using a deprecated (since 10.14) trick with locking - // a focus on a view, drawing, flushing CGContext and then unlocking. - // This stopped working since 10.15. So now the only thing - // we can do is to draw into a special transparent window which is - // attached on top of the canvas. - if (!fXorOps.size()) - return; - - assert(impl != 0 && "FlushXOROps, impl parameter is null"); - - NSObject * const drawable = impl->GetDrawable(fXorOps.back()->fID); - assert([drawable isKindOfClass : [QuartzView class]] && - "FlushXOROps, drawable must be of type QuartzView"); - QuartzView * const view = (QuartzView *)drawable; - for (auto *op : fXorOps) - op->setView(view); - QuartzWindow * const window = view.fQuartzWindow; - auto xorWindow = [window findXorWindow]; - if (!xorWindow) { - ::Warning("FlushXOROps", "No XorDrawingWindow found to draw into"); - ClearXOROperations(); - return; - } - - XorDrawingView *cv = (XorDrawingView *)xorWindow.contentView; - [cv setXorOperations: fXorOps]; // Pass the ownership of those objects. - fXorOps.clear(); // A view will free the memory. - [cv setNeedsDisplay : YES]; -} - //______________________________________________________________________________ void CommandBuffer::RemoveOperationsForDrawable(Drawable_t drawable) { @@ -650,13 +589,6 @@ fCommands[i] = 0; } } - - for (size_type i = 0; i < fXorOps.size(); ++i) { - if (fXorOps[i] && fXorOps[i]->HasOperand(drawable)) { - delete fXorOps[i]; - fXorOps[i] = 0; - } - } } //______________________________________________________________________________ @@ -672,17 +604,6 @@ } } -//______________________________________________________________________________ -void CommandBuffer::RemoveXORGraphicsOperationsForWindow(Window_t wid) -{ - for (size_type i = 0; i < fCommands.size(); ++i) { - if (fXorOps[i] && fXorOps[i]->HasOperand(wid)) { - delete fXorOps[i]; - fXorOps[i] = 0; - } - } -} - //______________________________________________________________________________ void CommandBuffer::ClearCommands() { @@ -692,15 +613,6 @@ fCommands.clear(); } -//______________________________________________________________________________ -void CommandBuffer::ClearXOROperations() -{ - for (size_type i = 0, e = fXorOps.size(); i < e; ++i) - delete fXorOps[i]; - - fXorOps.clear(); -} - //Clipping machinery. namespace { diff --git a/graf2d/freetype/src/freetype-2.12.1.tar.gz b/graf2d/freetype/src/freetype-2.12.1.tar.gz deleted file mode 100644 index 0d1b56dcbe394..0000000000000 Binary files a/graf2d/freetype/src/freetype-2.12.1.tar.gz and /dev/null differ diff --git a/graf2d/freetype/src/win/freetype.dep b/graf2d/freetype/src/win/freetype.dep deleted file mode 100644 index 99997fa9e5f32..0000000000000 --- a/graf2d/freetype/src/win/freetype.dep +++ /dev/null @@ -1,396 +0,0 @@ -# Microsoft Developer Studio Generated Dependency File, included by freetype.mak - -..\..\..\src\autofit\autofit.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\autofit\afangles.c"\ - "..\..\..\src\autofit\afcjk.c"\ - "..\..\..\src\autofit\afcjk.h"\ - "..\..\..\src\autofit\afdummy.c"\ - "..\..\..\src\autofit\afdummy.h"\ - "..\..\..\src\autofit\aferrors.h"\ - "..\..\..\src\autofit\afglobal.c"\ - "..\..\..\src\autofit\afglobal.h"\ - "..\..\..\src\autofit\afhints.c"\ - "..\..\..\src\autofit\afhints.h"\ - "..\..\..\src\autofit\afindic.c"\ - "..\..\..\src\autofit\afindic.h"\ - "..\..\..\src\autofit\aflatin.c"\ - "..\..\..\src\autofit\aflatin.h"\ - "..\..\..\src\autofit\aflatin2.c"\ - "..\..\..\src\autofit\aflatin2.h"\ - "..\..\..\src\autofit\afloader.c"\ - "..\..\..\src\autofit\afloader.h"\ - "..\..\..\src\autofit\afmodule.c"\ - "..\..\..\src\autofit\afmodule.h"\ - "..\..\..\src\autofit\aftypes.h"\ - "..\..\..\src\autofit\afwarp.c"\ - "..\..\..\src\autofit\afwarp.h"\ - - -..\..\..\src\bdf\bdf.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\bdf\bdf.h"\ - "..\..\..\src\bdf\bdfdrivr.c"\ - "..\..\..\src\bdf\bdfdrivr.h"\ - "..\..\..\src\bdf\bdferror.h"\ - "..\..\..\src\bdf\bdflib.c"\ - - -..\..\..\src\cff\cff.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\cff\cffcmap.c"\ - "..\..\..\src\cff\cffcmap.h"\ - "..\..\..\src\cff\cffdrivr.c"\ - "..\..\..\src\cff\cffdrivr.h"\ - "..\..\..\src\cff\cfferrs.h"\ - "..\..\..\src\cff\cffgload.c"\ - "..\..\..\src\cff\cffgload.h"\ - "..\..\..\src\cff\cffload.c"\ - "..\..\..\src\cff\cffload.h"\ - "..\..\..\src\cff\cffobjs.c"\ - "..\..\..\src\cff\cffobjs.h"\ - "..\..\..\src\cff\cffparse.c"\ - "..\..\..\src\cff\cffparse.h"\ - "..\..\..\src\cff\cfftoken.h"\ - "..\..\..\src\cff\cfftypes.h"\ - - -..\..\..\src\base\ftbase.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\base\ftcalc.c"\ - "..\..\..\src\base\ftdbgmem.c"\ - "..\..\..\src\base\ftgloadr.c"\ - "..\..\..\src\base\ftobjs.c"\ - "..\..\..\src\base\ftoutln.c"\ - "..\..\..\src\base\ftrfork.c"\ - "..\..\..\src\base\ftstream.c"\ - "..\..\..\src\base\fttrigon.c"\ - "..\..\..\src\base\ftutil.c"\ - - -..\..\..\src\base\ftbbox.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftbdf.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftbitmap.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\cache\ftcache.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\cache\ftcbasic.c"\ - "..\..\..\src\cache\ftccache.c"\ - "..\..\..\src\cache\ftccache.h"\ - "..\..\..\src\cache\ftccback.h"\ - "..\..\..\src\cache\ftccmap.c"\ - "..\..\..\src\cache\ftcerror.h"\ - "..\..\..\src\cache\ftcglyph.c"\ - "..\..\..\src\cache\ftcglyph.h"\ - "..\..\..\src\cache\ftcimage.c"\ - "..\..\..\src\cache\ftcimage.h"\ - "..\..\..\src\cache\ftcmanag.c"\ - "..\..\..\src\cache\ftcmanag.h"\ - "..\..\..\src\cache\ftcmru.c"\ - "..\..\..\src\cache\ftcmru.h"\ - "..\..\..\src\cache\ftcsbits.c"\ - "..\..\..\src\cache\ftcsbits.h"\ - - -..\ftdebug.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftgasp.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftglyph.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftgxval.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\gzip\ftgzip.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\gzip\adler32.c"\ - "..\..\..\src\gzip\infblock.c"\ - "..\..\..\src\gzip\infblock.h"\ - "..\..\..\src\gzip\infcodes.c"\ - "..\..\..\src\gzip\infcodes.h"\ - "..\..\..\src\gzip\inffixed.h"\ - "..\..\..\src\gzip\inflate.c"\ - "..\..\..\src\gzip\inftrees.c"\ - "..\..\..\src\gzip\inftrees.h"\ - "..\..\..\src\gzip\infutil.c"\ - "..\..\..\src\gzip\infutil.h"\ - "..\..\..\src\gzip\zconf.h"\ - "..\..\..\src\gzip\zlib.h"\ - "..\..\..\src\gzip\zutil.c"\ - "..\..\..\src\gzip\zutil.h"\ - - -..\..\..\src\base\ftinit.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\lzw\ftlzw.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\lzw\ftzopen.c"\ - "..\..\..\src\lzw\ftzopen.h"\ - - -..\..\..\src\base\ftmm.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftotval.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftpfr.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftstroke.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftsynth.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftsystem.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\fttype1.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftwinfnt.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\base\ftxf86.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - - -..\..\..\src\pcf\pcf.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\pcf\pcf.h"\ - "..\..\..\src\pcf\pcfdrivr.c"\ - "..\..\..\src\pcf\pcfdrivr.h"\ - "..\..\..\src\pcf\pcferror.h"\ - "..\..\..\src\pcf\pcfread.c"\ - "..\..\..\src\pcf\pcfread.h"\ - "..\..\..\src\pcf\pcfutil.c"\ - "..\..\..\src\pcf\pcfutil.h"\ - - -..\..\..\src\pfr\pfr.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\pfr\pfrcmap.c"\ - "..\..\..\src\pfr\pfrcmap.h"\ - "..\..\..\src\pfr\pfrdrivr.c"\ - "..\..\..\src\pfr\pfrdrivr.h"\ - "..\..\..\src\pfr\pfrerror.h"\ - "..\..\..\src\pfr\pfrgload.c"\ - "..\..\..\src\pfr\pfrgload.h"\ - "..\..\..\src\pfr\pfrload.c"\ - "..\..\..\src\pfr\pfrload.h"\ - "..\..\..\src\pfr\pfrobjs.c"\ - "..\..\..\src\pfr\pfrobjs.h"\ - "..\..\..\src\pfr\pfrsbit.c"\ - "..\..\..\src\pfr\pfrsbit.h"\ - "..\..\..\src\pfr\pfrtypes.h"\ - - -..\..\..\src\psaux\psaux.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\psaux\afmparse.c"\ - "..\..\..\src\psaux\afmparse.h"\ - "..\..\..\src\psaux\psauxerr.h"\ - "..\..\..\src\psaux\psauxmod.c"\ - "..\..\..\src\psaux\psauxmod.h"\ - "..\..\..\src\psaux\psconv.c"\ - "..\..\..\src\psaux\psconv.h"\ - "..\..\..\src\psaux\psobjs.c"\ - "..\..\..\src\psaux\psobjs.h"\ - "..\..\..\src\psaux\t1cmap.c"\ - "..\..\..\src\psaux\t1cmap.h"\ - "..\..\..\src\psaux\t1decode.c"\ - "..\..\..\src\psaux\t1decode.h"\ - - -..\..\..\src\pshinter\pshinter.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\pshinter\pshalgo.c"\ - "..\..\..\src\pshinter\pshalgo.h"\ - "..\..\..\src\pshinter\pshglob.c"\ - "..\..\..\src\pshinter\pshglob.h"\ - "..\..\..\src\pshinter\pshmod.c"\ - "..\..\..\src\pshinter\pshnterr.h"\ - "..\..\..\src\pshinter\pshrec.c"\ - "..\..\..\src\pshinter\pshrec.h"\ - - -..\..\..\src\psnames\psmodule.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\psnames\psmodule.h"\ - "..\..\..\src\psnames\psnamerr.h"\ - "..\..\..\src\psnames\pstables.h"\ - - -..\..\..\src\raster\raster.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\raster\ftmisc.h"\ - "..\..\..\src\raster\ftraster.c"\ - "..\..\..\src\raster\ftraster.h"\ - "..\..\..\src\raster\ftrend1.c"\ - "..\..\..\src\raster\ftrend1.h"\ - "..\..\..\src\raster\rasterrs.h"\ - - -..\..\..\src\sfnt\sfnt.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\sfnt\sfdriver.c"\ - "..\..\..\src\sfnt\sfdriver.h"\ - "..\..\..\src\sfnt\sferrors.h"\ - "..\..\..\src\sfnt\sfobjs.c"\ - "..\..\..\src\sfnt\sfobjs.h"\ - "..\..\..\src\sfnt\ttbdf.c"\ - "..\..\..\src\sfnt\ttbdf.h"\ - "..\..\..\src\sfnt\ttcmap.c"\ - "..\..\..\src\sfnt\ttcmap.h"\ - "..\..\..\src\sfnt\ttkern.c"\ - "..\..\..\src\sfnt\ttkern.h"\ - "..\..\..\src\sfnt\ttload.c"\ - "..\..\..\src\sfnt\ttload.h"\ - "..\..\..\src\sfnt\ttmtx.c"\ - "..\..\..\src\sfnt\ttmtx.h"\ - "..\..\..\src\sfnt\ttpost.c"\ - "..\..\..\src\sfnt\ttpost.h"\ - "..\..\..\src\sfnt\ttsbit.c"\ - "..\..\..\src\sfnt\ttsbit.h"\ - - -..\..\..\src\smooth\smooth.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\smooth\ftgrays.c"\ - "..\..\..\src\smooth\ftgrays.h"\ - "..\..\..\src\smooth\ftsmerrs.h"\ - "..\..\..\src\smooth\ftsmooth.c"\ - "..\..\..\src\smooth\ftsmooth.h"\ - - -..\..\..\src\truetype\truetype.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\truetype\ttdriver.c"\ - "..\..\..\src\truetype\ttdriver.h"\ - "..\..\..\src\truetype\tterrors.h"\ - "..\..\..\src\truetype\ttgload.c"\ - "..\..\..\src\truetype\ttgload.h"\ - "..\..\..\src\truetype\ttgxvar.c"\ - "..\..\..\src\truetype\ttgxvar.h"\ - "..\..\..\src\truetype\ttinterp.c"\ - "..\..\..\src\truetype\ttinterp.h"\ - "..\..\..\src\truetype\ttobjs.c"\ - "..\..\..\src\truetype\ttobjs.h"\ - "..\..\..\src\truetype\ttpload.c"\ - "..\..\..\src\truetype\ttpload.h"\ - - -..\..\..\src\type1\type1.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\type1\t1afm.c"\ - "..\..\..\src\type1\t1afm.h"\ - "..\..\..\src\type1\t1driver.c"\ - "..\..\..\src\type1\t1driver.h"\ - "..\..\..\src\type1\t1errors.h"\ - "..\..\..\src\type1\t1gload.c"\ - "..\..\..\src\type1\t1gload.h"\ - "..\..\..\src\type1\t1load.c"\ - "..\..\..\src\type1\t1load.h"\ - "..\..\..\src\type1\t1objs.c"\ - "..\..\..\src\type1\t1objs.h"\ - "..\..\..\src\type1\t1parse.c"\ - "..\..\..\src\type1\t1parse.h"\ - "..\..\..\src\type1\t1tokens.h"\ - - -..\..\..\src\cid\type1cid.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\cid\ciderrs.h"\ - "..\..\..\src\cid\cidgload.c"\ - "..\..\..\src\cid\cidgload.h"\ - "..\..\..\src\cid\cidload.c"\ - "..\..\..\src\cid\cidload.h"\ - "..\..\..\src\cid\cidobjs.c"\ - "..\..\..\src\cid\cidobjs.h"\ - "..\..\..\src\cid\cidparse.c"\ - "..\..\..\src\cid\cidparse.h"\ - "..\..\..\src\cid\cidriver.c"\ - "..\..\..\src\cid\cidriver.h"\ - "..\..\..\src\cid\cidtoken.h"\ - - -..\..\..\src\type42\type42.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\type42\t42drivr.c"\ - "..\..\..\src\type42\t42drivr.h"\ - "..\..\..\src\type42\t42error.h"\ - "..\..\..\src\type42\t42objs.c"\ - "..\..\..\src\type42\t42objs.h"\ - "..\..\..\src\type42\t42parse.c"\ - "..\..\..\src\type42\t42parse.h"\ - "..\..\..\src\type42\t42types.h"\ - - -..\..\..\src\winfonts\winfnt.c : \ - "..\..\..\include\freetype\config\ftheader.h"\ - "..\..\..\include\ft2build.h"\ - "..\..\..\src\winfonts\fnterrs.h"\ - "..\..\..\src\winfonts\winfnt.h"\ - diff --git a/graf2d/freetype/src/win/freetype.mak b/graf2d/freetype/src/win/freetype.mak deleted file mode 100644 index d58effbe84b0d..0000000000000 --- a/graf2d/freetype/src/win/freetype.mak +++ /dev/null @@ -1,662 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Based on freetype.dsp -!IF "$(CFG)" == "" -CFG=freetype - Win32 Debug Singlethreaded -!MESSAGE No configuration specified. Defaulting to freetype - Win32 Debug Singlethreaded. -!ENDIF - -!IF "$(CFG)" != "freetype - Win32 Release" && "$(CFG)" != "freetype - Win32 Debug" && "$(CFG)" != "freetype - Win32 Debug Multithreaded" && "$(CFG)" != "freetype - Win32 Release Multithreaded" && "$(CFG)" != "freetype - Win32 Release Singlethreaded" && "$(CFG)" != "freetype - Win32 Debug Singlethreaded" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "freetype.mak" CFG="freetype - Win32 Debug Singlethreaded" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "freetype - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "freetype - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE "freetype - Win32 Debug Multithreaded" (based on "Win32 (x86) Static Library") -!MESSAGE "freetype - Win32 Release Multithreaded" (based on "Win32 (x86) Static Library") -!MESSAGE "freetype - Win32 Release Singlethreaded" (based on "Win32 (x86) Static Library") -!MESSAGE "freetype - Win32 Debug Singlethreaded" (based on "Win32 (x86) Static Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -!IF "$(CFG)" == "freetype - Win32 Release" -OUTDIR=.\..\..\..\objs\release -INTDIR=.\..\..\..\objs\release -CPP_SWITCHES=$(NMAKECXXFLAGS) /Z7 /O2 /I "..\\..\\..\\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ELSEIF "$(CFG)" == "freetype - Win32 Debug" -OUTDIR=.\..\..\..\objs\debug -INTDIR=.\..\..\..\objs\debug -CPP_SWITCHES=$(NMAKECXXFLAGS) /Z7 /Od /I "..\\..\\..\\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT_DEBUG_LEVEL_ERROR" /D "FT_DEBUG_LEVEL_TRACE" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ELSEIF "$(CFG)" == "freetype - Win32 Debug Multithreaded" -OUTDIR=.\..\..\..\objs\debug_mt -INTDIR=.\..\..\..\objs\debug_mt -CPP_SWITCHES=$(NMAKECXXFLAGS) /Z7 /Od /I "..\\..\\..\\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT_DEBUG_LEVEL_ERROR" /D "FT_DEBUG_LEVEL_TRACE" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ELSEIF "$(CFG)" == "freetype - Win32 Release Multithreaded" -OUTDIR=.\..\..\..\objs\release_mt -INTDIR=.\..\..\..\objs\release_mt -CPP_SWITCHES=$(NMAKECXXFLAGS) /Z7 /O2 /I "..\\..\\..\\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ELSEIF "$(CFG)" == "freetype - Win32 Release Singlethreaded" -OUTDIR=.\..\..\..\objs\release_st -INTDIR=.\..\..\..\objs\release_st -CPP_SWITCHES=$(NMAKECXXFLAGS) /Z7 /O2 /I "..\\..\\..\\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ELSEIF "$(CFG)" == "freetype - Win32 Debug Singlethreaded" -OUTDIR=.\..\..\..\objs\debug_st -INTDIR=.\..\..\..\objs\debug_st -CPP_SWITCHES=$(NMAKECXXFLAGS) /Z7 /Od /I "..\\..\\..\\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT_DEBUG_LEVEL_ERROR" /D "FT_DEBUG_LEVEL_TRACE" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ENDIF - -LIB32_OBJS= \ - "$(INTDIR)\autofit.obj" \ - "$(INTDIR)\bdf.obj" \ - "$(INTDIR)\cff.obj" \ - "$(INTDIR)\ftbase.obj" \ - "$(INTDIR)\ftbbox.obj" \ - "$(INTDIR)\ftbdf.obj" \ - "$(INTDIR)\ftbitmap.obj" \ - "$(INTDIR)\ftcache.obj" \ - "$(INTDIR)\ftdebug.obj" \ - "$(INTDIR)\ftfstype.obj" \ - "$(INTDIR)\ftgasp.obj" \ - "$(INTDIR)\ftglyph.obj" \ - "$(INTDIR)\ftgxval.obj" \ - "$(INTDIR)\ftgzip.obj" \ - "$(INTDIR)\ftinit.obj" \ - "$(INTDIR)\ftlcdfil.obj" \ - "$(INTDIR)\ftlzw.obj" \ - "$(INTDIR)\ftmm.obj" \ - "$(INTDIR)\ftotval.obj" \ - "$(INTDIR)\ftpatent.obj" \ - "$(INTDIR)\ftpfr.obj" \ - "$(INTDIR)\ftstroke.obj" \ - "$(INTDIR)\ftsynth.obj" \ - "$(INTDIR)\ftsystem.obj" \ - "$(INTDIR)\fttype1.obj" \ - "$(INTDIR)\ftwinfnt.obj" \ - "$(INTDIR)\pcf.obj" \ - "$(INTDIR)\pfr.obj" \ - "$(INTDIR)\psaux.obj" \ - "$(INTDIR)\pshinter.obj" \ - "$(INTDIR)\psmodule.obj" \ - "$(INTDIR)\raster.obj" \ - "$(INTDIR)\sfnt.obj" \ - "$(INTDIR)\smooth.obj" \ - "$(INTDIR)\truetype.obj" \ - "$(INTDIR)\type1.obj" \ - "$(INTDIR)\type1cid.obj" \ - "$(INTDIR)\type42.obj" \ - "$(INTDIR)\winfnt.obj" - -!IF "$(CFG)" == "freetype - Win32 Release" - -ALL : "..\..\..\objs\freetype261.lib" - -CLEAN : - -@erase /q "$(INTDIR)\*.obj" >nul 2>&1 - -@erase /q "$(INTDIR)\*.idb" >nul 2>&1 - -@erase /q "..\..\..\objs\freetype261.lib" >nul 2>&1 - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=$(NMAKECXXFLAGS) /Z7 /O2 /I "..\\..\\..\\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\freetype.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"..\..\..\objs\freetype261.lib" - -"..\..\..\objs\freetype261.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "freetype - Win32 Debug" - -ALL : "..\..\..\objs\freetype261_D.lib" - -CLEAN : - -@erase /q "$(INTDIR)\*.obj" >nul 2>&1 - -@erase /q "$(INTDIR)\*.idb" >nul 2>&1 - -@erase /q "..\..\..\objs\freetype261_D.lib" >nul 2>&1 - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=$(NMAKECXXFLAGS) /Z7 /Od /I "..\\..\\..\\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT_DEBUG_LEVEL_ERROR" /D "FT_DEBUG_LEVEL_TRACE" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\freetype.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"..\..\..\objs\freetype261_D.lib" - -"..\..\..\objs\freetype261_D.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "freetype - Win32 Debug Multithreaded" - -ALL : "..\..\..\objs\freetype261MT_D.lib" - -CLEAN : - -@erase /q "$(INTDIR)\*.obj" >nul 2>&1 - -@erase /q "$(INTDIR)\*.idb" >nul 2>&1 - -@erase /q "..\..\..\objs\freetype261MT_D.lib" >nul 2>&1 - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=$(NMAKECXXFLAGS) /Z7 /Od /I "..\\..\\..\\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT_DEBUG_LEVEL_ERROR" /D "FT_DEBUG_LEVEL_TRACE" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\freetype.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"..\..\..\objs\freetype261MT_D.lib" - -"..\..\..\objs\freetype261MT_D.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "freetype - Win32 Release Multithreaded" - -ALL : "..\..\..\objs\freetype261MT.lib" - -CLEAN : - -@erase /q "$(INTDIR)\*.obj" >nul 2>&1 - -@erase /q "$(INTDIR)\*.idb" >nul 2>&1 - -@erase /q "..\..\..\objs\freetype261MT.lib" >nul 2>&1 - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=$(NMAKECXXFLAGS) /Z7 /O2 /I "..\\..\\..\\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\freetype.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"..\..\..\objs\freetype261MT.lib" - -"..\..\..\objs\freetype261MT.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "freetype - Win32 Release Singlethreaded" - -ALL : "..\..\..\objs\freetype261ST.lib" - -CLEAN : - -@erase /q "$(INTDIR)\*.obj" >nul 2>&1 - -@erase /q "$(INTDIR)\*.idb" >nul 2>&1 - -@erase /q "..\..\..\objs\freetype261ST.lib" >nul 2>&1 - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=$(NMAKECXXFLAGS) /Z7 /O2 /I "..\\..\\..\\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\freetype.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/out:"..\..\..\objs\freetype261ST.lib" - -"..\..\..\objs\freetype261ST.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "freetype - Win32 Debug Singlethreaded" - -ALL : "..\..\..\objs\freetype261ST_D.lib" - -CLEAN : - -@erase /q "$(INTDIR)\*.obj" >nul 2>&1 - -@erase /q "$(INTDIR)\*.idb" >nul 2>&1 - -@erase /q "..\..\..\objs\freetype261ST_D.lib" >nul 2>&1 - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -CPP_PROJ=$(NMAKECXXFLAGS) /Z7 /Od /I "..\\..\\..\\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "FT_DEBUG_LEVEL_ERROR" /D "FT_DEBUG_LEVEL_TRACE" /D "FT2_BUILD_LIBRARY" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -.c{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) -nologo @<< - $(CPP_PROJ) $< -<< - -RSC=rc.exe -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\freetype.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -LIB32_FLAGS=/nologo /out:"..\..\..\objs\freetype261ST_D.lib" - -"..\..\..\objs\freetype261ST_D.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ENDIF - - -!IF "$(NO_EXTERNAL_DEPS)" != "1" -!IF EXISTS("freetype.dep") -!INCLUDE "freetype.dep" -!ELSE -!MESSAGE Warning: cannot find "freetype.dep" -!ENDIF -!ENDIF - -SOURCE=..\..\..\src\autofit\autofit.c -"$(INTDIR)\autofit.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\bdf\bdf.c -"$(INTDIR)\bdf.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\cff\cff.c -"$(INTDIR)\cff.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftbase.c -"$(INTDIR)\ftbase.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftbbox.c -"$(INTDIR)\ftbbox.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftbdf.c -"$(INTDIR)\ftbdf.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftbitmap.c -"$(INTDIR)\ftbitmap.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\cache\ftcache.c -"$(INTDIR)\ftcache.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\ftdebug.c -"$(INTDIR)\ftdebug.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftfstype.c -"$(INTDIR)\ftfstype.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftgasp.c -"$(INTDIR)\ftgasp.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftglyph.c -"$(INTDIR)\ftglyph.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftgxval.c -"$(INTDIR)\ftgxval.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=..\..\..\src\gzip\ftgzip.c -"$(INTDIR)\ftgzip.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftinit.c -"$(INTDIR)\ftinit.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftlcdfil.c -"$(INTDIR)\ftlcdfil.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\lzw\ftlzw.c -"$(INTDIR)\ftlzw.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftmm.c -"$(INTDIR)\ftmm.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftotval.c -"$(INTDIR)\ftotval.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftpatent.c -"$(INTDIR)\ftpatent.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\ftpfr.c -"$(INTDIR)\ftpfr.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftstroke.c -"$(INTDIR)\ftstroke.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftsynth.c -"$(INTDIR)\ftsynth.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftsystem.c -"$(INTDIR)\ftsystem.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\base\fttype1.c -"$(INTDIR)\fttype1.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\base\ftwinfnt.c -"$(INTDIR)\ftwinfnt.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\pcf\pcf.c -"$(INTDIR)\pcf.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\pfr\pfr.c -"$(INTDIR)\pfr.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=..\..\..\src\psaux\psaux.c -"$(INTDIR)\psaux.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\pshinter\pshinter.c -"$(INTDIR)\pshinter.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\psnames\psmodule.c -"$(INTDIR)\psmodule.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\raster\raster.c -"$(INTDIR)\raster.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\sfnt\sfnt.c -"$(INTDIR)\sfnt.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\smooth\smooth.c -"$(INTDIR)\smooth.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\truetype\truetype.c -"$(INTDIR)\truetype.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\type1\type1.c -"$(INTDIR)\type1.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\cid\type1cid.c -"$(INTDIR)\type1cid.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\type42\type42.c -"$(INTDIR)\type42.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - -SOURCE=..\..\..\src\winfonts\winfnt.c -"$(INTDIR)\winfnt.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) -nologo @<< - $(CPP_SWITCHES) $(SOURCE) -<< - diff --git a/graf2d/gpad/CMakeLists.txt b/graf2d/gpad/CMakeLists.txt index f8269981882a0..e6e8e400fed85 100644 --- a/graf2d/gpad/CMakeLists.txt +++ b/graf2d/gpad/CMakeLists.txt @@ -24,6 +24,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Gpad TGroupButton.h TInspectCanvas.h TPad.h + TPadPainterBase.h TPadPainter.h TPadPainterPS.h TPaveClass.h diff --git a/graf2d/gpad/inc/LinkDef.h b/graf2d/gpad/inc/LinkDef.h index a1f86884bc051..eeb1d68c513ff 100644 --- a/graf2d/gpad/inc/LinkDef.h +++ b/graf2d/gpad/inc/LinkDef.h @@ -31,6 +31,7 @@ #pragma link C++ class TSliderBox+; #pragma link C++ class TView+; #pragma link C++ class TViewer3DPad; +#pragma link C++ class TPadPainterBase; #pragma link C++ class TPadPainter; #pragma link C++ class TPadPainterPS; #pragma link C++ class TRatioPlot+; diff --git a/graf2d/gpad/inc/TCanvas.h b/graf2d/gpad/inc/TCanvas.h index df7dd24c8a51e..e1acdedcbcc1b 100644 --- a/graf2d/gpad/inc/TCanvas.h +++ b/graf2d/gpad/inc/TCanvas.h @@ -66,6 +66,8 @@ friend class TInterpreter; // TVirtualPadPainter *fPainter; ///SelectWindow(fCanvasID); - gVirtualX->SetFillColor(1); //Set color index for fill area - gVirtualX->SetLineColor(1); //Set color index for lines - gVirtualX->SetMarkerColor(1); //Set color index for markers - gVirtualX->SetTextColor(1); //Set color index for text + fPainter->SelectDrawable(fCanvasID); + fPainter->SetAttFill({1, 1001}); //Set color index for fill area + fPainter->SetAttLine({1, 1, 1}); //Set color index for lines + fPainter->SetAttMarker({1, 1, 1}); //Set color index for markers + fPainter->SetAttText({22, 0., 1, 42, 12}); //Set color index for text // Clear workstation - gVirtualX->ClearWindow(); + fPainter->ClearDrawable(); // Set Double Buffer on by default SetDoubleBuffer(1); @@ -627,8 +626,7 @@ void TCanvas::Build() fWindowWidth, fWindowHeight); // Get effective canvas parameters without borders - Int_t dum1, dum2; - gVirtualX->GetGeometry(fCanvasID, dum1, dum2, fCw, fCh); + fCanvasImp->GetCanvasGeometry(fCanvasID, fCw, fCh); fContextMenu = new TContextMenu("ContextMenu"); } @@ -722,8 +720,8 @@ TVirtualPad *TCanvas::cd(Int_t subpadnumber) TPad::cd(subpadnumber); // in case doublebuffer is off, draw directly onto display window - if (!IsBatch() && !IsWeb() && !fDoubleBuffer) - gVirtualX->SelectWindow(fCanvasID);//Ok, does not matter for glpad. + if (!IsBatch() && !IsWeb() && !fDoubleBuffer && fPainter) + fPainter->SelectDrawable(fCanvasID);//Ok, does not matter for glpad. return gPad; } @@ -804,7 +802,9 @@ void TCanvas::Close(Option_t *option) TPad::Close(option); if (!IsBatch() && !IsWeb()) { - gVirtualX->SelectWindow(fCanvasID); //select current canvas + //select current canvas + if (fPainter) + fPainter->SelectDrawable(fCanvasID); DeleteCanvasPainter(); @@ -835,7 +835,7 @@ void TCanvas::Close(Option_t *option) void TCanvas::CopyPixmaps() { if (!IsBatch()) { - CopyPixmap(); + TPad::CopyPixmap(); TPad::CopyPixmaps(); } } @@ -1126,16 +1126,13 @@ void TCanvas::ExecuteEvent(Int_t event, Int_t px, Int_t py) void TCanvas::FeedbackMode(Bool_t set) { - if (IsWeb()) + if (IsWeb() || (fCanvasID == -1)) return; - if (set) { - SetDoubleBuffer(0); // turn off double buffer mode - gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode - } else { - SetDoubleBuffer(1); // turn on double buffer mode - gVirtualX->SetDrawMode(TVirtualX::kCopy); // set drawing mode back to normal (copy) mode - } + SetDoubleBuffer(set ? 0 : 1); // switch double buffer + + if (fPainter) + fPainter->SetDrawMode(fCanvasID, set ? TVirtualX::kInvert : TVirtualX::kCopy); } //////////////////////////////////////////////////////////////////////////////// @@ -1143,30 +1140,28 @@ void TCanvas::FeedbackMode(Bool_t set) void TCanvas::Flush() { - if ((fCanvasID == -1) || IsWeb()) return; + if ((fCanvasID == -1) || IsWeb() || IsBatch()) + return; - TContext ctxt(this, kTRUE); - if (!IsBatch()) { - if (!UseGL() || fGLDevice == -1) { - gVirtualX->SelectWindow(fCanvasID); - gPad = ctxt.GetSaved(); //don't do cd() because than also the pixmap is changed - CopyPixmaps(); - gVirtualX->UpdateWindow(1); - } else { - TVirtualPS *tvps = gVirtualPS; - gVirtualPS = nullptr; - gGLManager->MakeCurrent(fGLDevice); - fPainter->InitPainter(); - Paint(); - if (ctxt.GetSaved() && ctxt.GetSaved()->GetCanvas() == this) { - ctxt.GetSaved()->cd(); - ctxt.GetSaved()->HighLight(ctxt.GetSaved()->GetHighLightColor()); - //cd(); - } - fPainter->LockPainter(); - gGLManager->Flush(fGLDevice); - gVirtualPS = tvps; - } + if (!UseGL() || fGLDevice == -1) { + fPainter->SelectDrawable(fCanvasID); + CopyPixmaps(); + fPainter->UpdateDrawable(1); + } else { + if (IsEditable()) + fHilightPadBorder = gPad; + + TContext ctxt(this, kTRUE); + + TVirtualPS *tvps = gVirtualPS; + gVirtualPS = nullptr; + gGLManager->MakeCurrent(fGLDevice); + fPainter->InitPainter(); + Paint(); + fPainter->LockPainter(); + gGLManager->Flush(fGLDevice); + gVirtualPS = tvps; + fHilightPadBorder = nullptr; } } @@ -1265,7 +1260,7 @@ void TCanvas::HandleInput(EEventType event, Int_t px, Int_t py) case kMouseEnter: // mouse enters canvas - if (!fDoubleBuffer) FeedbackMode(kTRUE); + //FeedbackMode(kTRUE); break; case kMouseLeave: @@ -1279,7 +1274,7 @@ void TCanvas::HandleInput(EEventType event, Int_t px, Int_t py) EnterLeave(prevSelPad, prevSelObj); fSelected = sobj; fSelectedPad = spad; - if (!fDoubleBuffer) FeedbackMode(kFALSE); + //FeedbackMode(kFALSE); } break; @@ -1312,8 +1307,7 @@ void TCanvas::HandleInput(EEventType event, Int_t px, Int_t py) gPad = fSelectedPad; fSelected->ExecuteEvent(event, px, py); - if (!IsWeb()) - gVirtualX->Update(); + fCanvasImp->UpdateDisplay(0); if (fSelected && !fSelected->InheritsFrom(TAxis::Class())) { Bool_t resize = kFALSE; if (fSelected->InheritsFrom(TBox::Class())) @@ -1666,7 +1660,8 @@ void TCanvas::ProcessedEvent(Int_t event, Int_t x, Int_t y, TObject *obj) void TCanvas::Resize(Option_t *) { - if (fCanvasID == -1) return; + if (fCanvasID == -1) + return; if (!gROOT->IsLineProcessing() && !gVirtualX->IsCmdThread()) { gInterpreter->Execute(this, IsA(), "Resize", ""); @@ -1678,16 +1673,17 @@ void TCanvas::Resize(Option_t *) TContext ctxt(this, kTRUE); if (!IsBatch() && !IsWeb()) { - gVirtualX->SelectWindow(fCanvasID); //select current canvas - gVirtualX->ResizeWindow(fCanvasID); //resize canvas and off-screen buffer + // SL: do we need it here? + fPainter->SelectDrawable(fCanvasID); //select current canvas for painting??? + + fCanvasImp->ResizeCanvasWindow(fCanvasID); //resize canvas and off-screen buffer // Get effective window parameters including menubar and borders fCanvasImp->GetWindowGeometry(fWindowTopX, fWindowTopY, fWindowWidth, fWindowHeight); // Get effective canvas parameters without borders - Int_t dum1, dum2; - gVirtualX->GetGeometry(fCanvasID, dum1, dum2, fCw, fCh); + fCanvasImp->GetCanvasGeometry(fCanvasID, fCw, fCh); } if (fXsizeUser && fYsizeUser) { @@ -1732,7 +1728,7 @@ void TCanvas::Resize(Option_t *) fYsizeReal = fXsizeReal*Double_t(fCh)/Double_t(fCw); } -//*-*- Loop on all pads to recompute conversion coefficients + //*-*- Loop on all pads to recompute conversion coefficients TPad::ResizePad(); } @@ -1965,8 +1961,8 @@ void TCanvas::SetCanvasSize(UInt_t ww, UInt_t wh) void TCanvas::SetCursor(ECursor cursor) { - if (!IsBatch() && !IsWeb()) - gVirtualX->SetCursor(fCanvasID, cursor); + if (!IsBatch() && !IsWeb() && fCanvasID != -1) + fPainter->SetCursor(fCanvasID, cursor); } //////////////////////////////////////////////////////////////////////////////// @@ -1977,7 +1973,8 @@ void TCanvas::SetDoubleBuffer(Int_t mode) if (IsBatch() || IsWeb()) return; fDoubleBuffer = mode; - gVirtualX->SetDoubleBuffer(fCanvasID, mode); + if (fCanvasID != -1) + fPainter->SetDoubleBuffer(fCanvasID, mode); // depending of the buffer mode set the drawing window to either // the canvas pixmap or to the canvas on-screen window @@ -2476,8 +2473,10 @@ void TCanvas::ToggleToolTips() Bool_t TCanvas::SupportAlpha() { - return gPad && (gVirtualX->InheritsFrom("TGQuartz") || - (gPad->GetGLDevice() != -1) || (gPad->GetCanvas() && gPad->GetCanvas()->IsWeb())); + if (gPad) + if (auto pp = gPad->GetPainter()) + return pp->IsSupportAlpha(); + return kFALSE; } extern "C" void ROOT_TCanvas_Update(void* TheCanvas) { @@ -2597,7 +2596,7 @@ void TCanvas::CreatePainter() { //Even for batch mode painter is still required, just to delegate //some calls to batch "virtual X". - if (!UseGL() || fBatch) { + if (!UseGL() || fBatch || IsWeb()) { fPainter = nullptr; if (fCanvasImp) fPainter = fCanvasImp->CreatePadPainter(); if (!fPainter) fPainter = new TPadPainter; // Do not need plugin manager for this! @@ -2632,7 +2631,7 @@ Bool_t TCanvas::EnsurePSPainter(Bool_t create, TVirtualPadPainter *&oldp) return kFALSE; } - if (!gVirtualPS || !IsBatch()) + if (!gVirtualPS /* || !IsBatch() */) return kFALSE; diff --git a/graf2d/gpad/src/TPad.cxx b/graf2d/gpad/src/TPad.cxx index ca927656b89a6..cdc161429fbef 100644 --- a/graf2d/gpad/src/TPad.cxx +++ b/graf2d/gpad/src/TPad.cxx @@ -46,10 +46,12 @@ #include "TMethod.h" #include "TDataType.h" #include "TFrame.h" +#include "TWbox.h" #include "TExec.h" #include "TDatime.h" #include "TColor.h" #include "TCanvas.h" +#include "TCanvasImp.h" #include "TPluginManager.h" #include "TEnv.h" #include "TImage.h" @@ -1146,10 +1148,9 @@ void TPad::CopyPixmap() int px, py; XYtoAbsPixel(fX1, fY2, px, py); - if (fPixmapID != -1 && GetPainter()) - GetPainter()->CopyDrawable(fPixmapID, px, py); - - if (this == gPad) HighLight(gPad->GetHighLightColor()); + if (fPixmapID != -1) + if (auto pp = GetPainter()) + pp->CopyDrawable(fPixmapID, px, py); } //////////////////////////////////////////////////////////////////////////////// @@ -1157,14 +1158,18 @@ void TPad::CopyPixmap() void TPad::CopyPixmaps() { - if (!fPrimitives) fPrimitives = new TList; - TIter next(GetListOfPrimitives()); + if (!fPrimitives) + fPrimitives = new TList; + TIter next(GetListOfPrimitives()); while (auto obj = next()) { - if (obj->InheritsFrom(TPad::Class())) { - ((TPad*)obj)->CopyPixmap(); - ((TPad*)obj)->CopyPixmaps(); + if (auto pad = dynamic_cast(obj)) { + pad->CopyPixmap(); + pad->CopyPixmaps(); } } + + if (this == gPad) + HighLight(GetHighLightColor()); } //////////////////////////////////////////////////////////////////////////////// @@ -1750,44 +1755,58 @@ void TPad::DrawClassObject(const TObject *classobj, Option_t *option) void TPad::DrawCrosshair() { - if (!gPad || (gPad->GetEvent() == kMouseEnter)) return; + if (!gPad || (gPad->GetEvent() == kMouseEnter)) + return; TPad *cpad = (TPad*)gPad; TCanvas *canvas = cpad->GetCanvas(); + // switch off double buffer and select canvas drawable canvas->FeedbackMode(kTRUE); + auto pp = GetPainter(); + //erase old position and draw a line at current position - Int_t pxmin,pxmax,pymin,pymax,px,py; -#ifndef R__HAS_COCOA - Int_t pxold = fCrosshairPos%10000; - Int_t pyold = fCrosshairPos/10000; -#endif // R__HAS_COCOA - px = cpad->GetEventX(); - py = cpad->GetEventY()+1; + Double_t umin, umax, vmin, vmax, u, v; + Int_t px = cpad->GetEventX(); + Int_t py = cpad->GetEventY() + 1; if (canvas->GetCrosshair() > 1) { //crosshair only in the current pad - pxmin = cpad->XtoAbsPixel(fX1); - pxmax = cpad->XtoAbsPixel(fX2); - pymin = cpad->YtoAbsPixel(fY1); - pymax = cpad->YtoAbsPixel(fY2); + umin = GetAbsXlowNDC(); + umax = GetAbsXlowNDC() + GetAbsWNDC(); + vmin = GetAbsYlowNDC(); + vmax = GetAbsYlowNDC() + GetAbsHNDC(); } else { //default; crosshair spans the full canvas - pxmin = 0; - pxmax = canvas->GetWw(); - pymin = 0; - pymax = cpad->GetWh(); - } -#ifndef R__HAS_COCOA - // Not needed, no XOR with Cocoa. - if(pxold) gVirtualX->DrawLine(pxold,pymin,pxold,pymax); - if(pyold) gVirtualX->DrawLine(pxmin,pyold,pxmax,pyold); -#endif // R__HAS_COCOA + umin = 0; + umax = 1; + vmin = 0; + vmax = 1; + } + + TContext ctxt(canvas); + + pp->SetAttLine({1,1,1}); + + if ((fCrosshairPos != 0) && !pp->IsCocoa()) { + // xor does not supported on Cocoa, implemented differently + Int_t pxold = fCrosshairPos % 10000; + Int_t pyold = fCrosshairPos / 10000; + u = 1. * pxold / canvas->GetWw(); + v = 1. - 1. * pyold / canvas->GetWh(); + pp->DrawLineNDC(umin, v, umax, v); + pp->DrawLineNDC(u, vmin, u, vmax); + } + if (cpad->GetEvent() == kButton1Down || cpad->GetEvent() == kButton1Up || cpad->GetEvent() == kMouseLeave) { fCrosshairPos = 0; return; } - gVirtualX->DrawLine(px,pymin,px,pymax); - gVirtualX->DrawLine(pxmin,py,pxmax,py); + + u = 1. * px / canvas->GetWw(); + v = 1. - 1. * py / canvas->GetWh(); + pp->DrawLineNDC(umin, v, umax, v); + pp->DrawLineNDC(u, vmin, u, vmax); + fCrosshairPos = px + 10000*py; } @@ -1931,35 +1950,27 @@ void TPad::DrawColorTable() void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - const Int_t kMaxDiff = 5; - const Int_t kMinSize = 20; - static Int_t pxorg, pyorg; - static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold; - static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp; - static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE; - Int_t wx, wy; + constexpr Int_t kMaxDiff = 5; + constexpr Int_t kMinSize = 20; + static Int_t px1, px2, py1, py2, dpx1, dpy2; + static Int_t px1p, px2p, py1p, py2p; + static enum { pNone, pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE } mode = pNone; + static Bool_t firstPaint = kFALSE; Bool_t opaque = OpaqueMoving(); Bool_t ropaque = OpaqueResizing(); - Bool_t fixedr = HasFixedAspectRatio(); if (!IsEditable() && event != kMouseEnter) return; - TVirtualPad *parent = GetMother(); - if (!parent->IsEditable()) return; + TVirtualPad &parent = *GetMother(); + if (!parent.IsEditable()) return; HideToolTip(event); if (fXlowNDC < 0 && event != kButton1Down) return; if (fYlowNDC < 0 && event != kButton1Down) return; - // keep old mouse position - if (event == kButton1Down) { - pxorg = px; - pyorg = py; - } - Int_t newcode = gROOT->GetEditorMode(); if (newcode) - pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE; + mode = pNone; switch (newcode) { case kPad: TCreatePrimitives::Pad(event,px,py,0); @@ -2002,8 +2013,77 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) return; default: break; + } + if (newcode) + return; + + auto paint_or_set = [this, &parent](Bool_t paint) + { + auto x1 = AbsPixeltoX(px1); + auto y1 = AbsPixeltoY(py1); + auto x2 = AbsPixeltoX(px2); + auto y2 = AbsPixeltoY(py2); + if (!paint) { + // Get parent corners pixels coordinates + Int_t parentpx1 = fMother->XtoAbsPixel(parent.GetX1()); + Int_t parentpx2 = fMother->XtoAbsPixel(parent.GetX2()); + Int_t parentpy1 = fMother->YtoAbsPixel(parent.GetY1()); + Int_t parentpy2 = fMother->YtoAbsPixel(parent.GetY2()); + + // Get pad new corners pixels coordinates + Int_t apx1 = XtoAbsPixel(x1); if (apx1 < parentpx1) {apx1 = parentpx1; } + Int_t apx2 = XtoAbsPixel(x2); if (apx2 > parentpx2) {apx2 = parentpx2; } + Int_t apy1 = YtoAbsPixel(y1); if (apy1 > parentpy1) {apy1 = parentpy1; } + Int_t apy2 = YtoAbsPixel(y2); if (apy2 < parentpy2) {apy2 = parentpy2; } + + // Compute new pad positions in the NDC space of parent + fXlowNDC = Double_t(apx1 - parentpx1)/Double_t(parentpx2 - parentpx1); + fYlowNDC = Double_t(apy1 - parentpy1)/Double_t(parentpy2 - parentpy1); + fWNDC = Double_t(apx2 - apx1)/Double_t(parentpx2 - parentpx1); + fHNDC = Double_t(apy2 - apy1)/Double_t(parentpy2 - parentpy1); + } else if (firstPaint) { + // first paint with original coordinates not required + firstPaint = kFALSE; + } else { + auto pp = GetPainter(); + pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2}); + pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); + } + }; + + Int_t prevpx1 = px1, prevpx2 = px2, prevpy1 = py1, prevpy2 = py2; + + // function check how to restore pad ratio + auto adjustRatio = [this, &parent](int choise = 11) -> bool + { + if (!HasFixedAspectRatio()) + return true; // do nothing + + if (choise == 11) { + Int_t dx = parent.UtoPixel(fAspectRatio * (py1 - py2) / parent.VtoPixel(0)); + Int_t npx1 = (px1 + px2) / 2 - dx / 2; + Int_t npx2 = npx1 + dx; + if ((npx1 >= px1p) && (npx2 <= px2p)) { + px1 = npx1; px2 = npx2; + return true; + } + } else { + Int_t dy = parent.VtoPixel(1. - (0. + px2 - px1) / parent.UtoPixel(1.) / fAspectRatio); + Int_t npy1 = py1; + Int_t npy2 = py2; + switch (choise) { + case -1: npy2 = py1 - dy; break; + case 0: npy2 = (py1 + py2) / 2 - dy / 2; npy1 = npy2 + dy; break; + case 1: npy1 = py2 + dy; break; + } + if ((npy1 <= py1p) && (npy2 >= py2p)) { + py1 = npy1; py2 = npy2; + return true; + } } - if (newcode) return; + + return false; // fail to adjust ratio, need to restore values + }; switch (event) { @@ -2018,14 +2098,6 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) fXUpNDC = fXlowNDC + fWNDC; fYUpNDC = fYlowNDC + fHNDC; - GetPainter()->SetLineColor(-1); - TAttLine::Modify(); //Change line attributes only if necessary - if (GetFillColor()) - GetPainter()->SetLineColor(GetFillColor()); - else - GetPainter()->SetLineColor(1); - GetPainter()->SetLineWidth(2); - // No break !!! case kMouseMotion: @@ -2035,102 +2107,63 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) px2 = XtoAbsPixel(fX2); py2 = YtoAbsPixel(fY2); - if (px1 < px2) { - pxl = px1; - pxt = px2; - } else { - pxl = px2; - pxt = px1; - } - if (py1 < py2) { - pyl = py1; - pyt = py2; - } else { - pyl = py2; - pyt = py1; - } + if (px1 > px2) + std::swap(px1, px2); - px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize(); - py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize(); - px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize(); - py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize(); + if (py1 < py2) + std::swap(py1, py2); - if (px1p < px2p) { - pxlp = px1p; - pxtp = px2p; - } else { - pxlp = px2p; - pxtp = px1p; - } - if (py1p < py2p) { - pylp = py1p; - pytp = py2p; - } else { - pylp = py2p; - pytp = py1p; - } + px1p = parent.XtoAbsPixel(parent.GetX1()) + parent.GetBorderSize(); + py1p = parent.YtoAbsPixel(parent.GetY1()) - parent.GetBorderSize(); + px2p = parent.XtoAbsPixel(parent.GetX2()) - parent.GetBorderSize(); + py2p = parent.YtoAbsPixel(parent.GetY2()) + parent.GetBorderSize(); + + if (px1p > px2p) + std::swap(px1p, px2p); - pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE; + if (py1p < py2p) + std::swap(py1p, py2p); - // case pA - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxl; pyold = pyl; pA = kTRUE; + mode = pNone; + if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pA; SetCursor(kTopLeft); - } - // case pB - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxt; pyold = pyl; pB = kTRUE; + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pB; SetCursor(kTopRight); - } - // case pC - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxt; pyold = pyt; pC = kTRUE; + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pC; SetCursor(kBottomRight); - } - // case pD - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxl; pyold = pyt; pD = kTRUE; + } else if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pD; SetCursor(kBottomLeft); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - TMath::Abs(py - pyl) < kMaxDiff) { // top edge - pxold = pxl; pyold = pyl; pTop = kTRUE; + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py2) < kMaxDiff) { + mode = pTop; SetCursor(kTopSide); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - TMath::Abs(py - pyt) < kMaxDiff) { // bottom edge - pxold = pxt; pyold = pyt; pBot = kTRUE; + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py1) < kMaxDiff) { + mode = pBot; SetCursor(kBottomSide); - } - - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && - TMath::Abs(px - pxl) < kMaxDiff) { // left edge - pxold = pxl; pyold = pyl; pL = kTRUE; + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px1) < kMaxDiff) { + mode = pL; SetCursor(kLeftSide); - } - - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && - TMath::Abs(px - pxt) < kMaxDiff) { // right edge - pxold = pxt; pyold = pyt; pR = kTRUE; + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px2) < kMaxDiff) { + mode = pR; SetCursor(kRightSide); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { // inside box - pxold = px; pyold = py; pINSIDE = kTRUE; + } else if ((px > px1+kMaxDiff && px < px2-kMaxDiff) && (py > py2+kMaxDiff && py < py1-kMaxDiff)) { + dpx1 = px - px1; // cursor position relative to top-left corner + dpy2 = py - py2; + mode = pINSIDE; if (event == kButton1Down) SetCursor(kMove); else SetCursor(kCross); } - fResizing = kFALSE; - if (pA || pB || pC || pD || pTop || pL || pR || pBot) - fResizing = kTRUE; + fResizing = (mode != pNone) && (mode != pINSIDE); + + firstPaint = kTRUE; - if (!pA && !pB && !pC && !pD && !pTop && !pL && !pR && !pBot && !pINSIDE) + if (mode == pNone) SetCursor(kCross); break; @@ -2139,247 +2172,107 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) case kButton1Motion: if (TestBit(kCannotMove)) break; - wx = wy = 0; - - if (pA) { - if (!ropaque) gVirtualX->DrawBox(pxold, pyt, pxt, pyold, TVirtualX::kHollow); - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < pylp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) gVirtualX->DrawBox(px, pyt, pxt, py, TVirtualX::kHollow); - } - if (pB) { - if (!ropaque) gVirtualX->DrawBox(pxl , pyt, pxold, pyold, TVirtualX::kHollow); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < pylp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) gVirtualX->DrawBox(pxl , pyt, px , py, TVirtualX::kHollow); - } - if (pC) { - if (!ropaque) gVirtualX->DrawBox(pxl , pyl, pxold, pyold, TVirtualX::kHollow); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 > pytp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) gVirtualX->DrawBox(pxl, pyl, px, py, TVirtualX::kHollow); - } - if (pD) { - if (!ropaque) gVirtualX->DrawBox(pxold, pyold, pxt, pyl, TVirtualX::kHollow); - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 > pytp) { - px = pxold; - py = pyold; - } else - py = npy2; - - wx = wy = 0; - } - if (!ropaque) gVirtualX->DrawBox(px, py, pxt, pyl, TVirtualX::kHollow); - } - if (pTop) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - py2 += py - pyold; - if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; } - if (py2 < py2p) { py2 = py2p; wy = py2; } - if (fixedr) { - Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) * - fAspectRatio; - Int_t npx2 = px1 + parent->UtoPixel(dx); - if (npx2 > px2p) - py2 -= py - pyold; - else - px2 = npx2; - } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pBot) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - py1 += py - pyold; - if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; } - if (py1 > py1p) { py1 = py1p; wy = py1; } - if (fixedr) { - Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) * - fAspectRatio; - Int_t npx2 = px1 + parent->UtoPixel(dx); - if (npx2 > px2p) - py1 -= py - pyold; - else - px2 = npx2; - } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pL) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - px1 += px - pxold; - if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; } - if (px1 < px1p) { px1 = px1p; wx = px1; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < py2p) - px1 -= px - pxold; - else - py2 = npy2; - } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pR) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - px2 += px - pxold; - if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; } - if (px2 > px2p) { px2 = px2p; wx = px2; } - if (fixedr) { - Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) / - fAspectRatio; - Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) - - parent->VtoAbsPixel(0)); - if (npy2 < py2p) - px2 -= px - pxold; - else - py2 = npy2; - } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pINSIDE) { - if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the old box - Int_t dx = px - pxold; - Int_t dy = py - pyold; - px1 += dx; py1 += dy; px2 += dx; py2 += dy; - if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; } - if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; } - if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; } - if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; } - if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the new box - } - - if (wx || wy) { - if (wx) px = wx; - if (wy) py = wy; - gVirtualX->Warp(px, py); - } - - pxold = px; - pyold = py; - - Double_t x1, y1, x2, y2; - x1 = x2 = y1 = y2 = 0; - - if ((!fResizing && opaque) || (fResizing && ropaque)) { - if (pA) { - x1 = AbsPixeltoX(pxold); - y1 = AbsPixeltoY(pyt); - x2 = AbsPixeltoX(pxt); - y2 = AbsPixeltoY(pyold); - } - if (pB) { - x1 = AbsPixeltoX(pxl); - y1 = AbsPixeltoY(pyt); - x2 = AbsPixeltoX(pxold); - y2 = AbsPixeltoY(pyold); - } - if (pC) { - x1 = AbsPixeltoX(pxl); - y1 = AbsPixeltoY(pyold); - x2 = AbsPixeltoX(pxold); - y2 = AbsPixeltoY(pyl); + + switch (mode) { + case pNone: + return; + case pA: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + if (!adjustRatio(-1)) { + px1 = prevpx1; + py2 = prevpy2; } - if (pD) { - x1 = AbsPixeltoX(pxold); - y1 = AbsPixeltoY(pyold); - x2 = AbsPixeltoX(pxt); - y2 = AbsPixeltoY(pyl); + paint_or_set(!ropaque); + break; + case pB: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + if (!adjustRatio(-1)) { + px2 = prevpx2; + py2 = prevpy2; } - if (pTop || pBot || pL || pR || pINSIDE) { - x1 = AbsPixeltoX(px1); - y1 = AbsPixeltoY(py1); - x2 = AbsPixeltoX(px2); - y2 = AbsPixeltoY(py2); + paint_or_set(!ropaque); + break; + case pC: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + if (!adjustRatio(1)) { + px2 = prevpx2; + py1 = prevpy1; } - - if (px != pxorg || py != pyorg) { - - // Get parent corners pixels coordinates - Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1()); - Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2()); - Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1()); - Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2()); - - // Get pad new corners pixels coordinates - Int_t apx1 = XtoAbsPixel(x1); if (apx1 < parentpx1) {apx1 = parentpx1; } - Int_t apx2 = XtoAbsPixel(x2); if (apx2 > parentpx2) {apx2 = parentpx2; } - Int_t apy1 = YtoAbsPixel(y1); if (apy1 > parentpy1) {apy1 = parentpy1; } - Int_t apy2 = YtoAbsPixel(y2); if (apy2 < parentpy2) {apy2 = parentpy2; } - - // Compute new pad positions in the NDC space of parent - fXlowNDC = Double_t(apx1 - parentpx1)/Double_t(parentpx2 - parentpx1); - fYlowNDC = Double_t(apy1 - parentpy1)/Double_t(parentpy2 - parentpy1); - fWNDC = Double_t(apx2 - apx1)/Double_t(parentpx2 - parentpx1); - fHNDC = Double_t(apy2 - apy1)/Double_t(parentpy2 - parentpy1); + paint_or_set(!ropaque); + break; + case pD: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + if (!adjustRatio(1)) { + px1 = prevpx1; + py1 = prevpy1; } + paint_or_set(!ropaque); + break; + case pTop: + if (!ropaque) paint_or_set(kTRUE); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + if (!adjustRatio(11)) + py2 = prevpy2; + paint_or_set(!ropaque); + break; + case pBot: + if (!ropaque) paint_or_set(kTRUE); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + if (!adjustRatio(11)) + py1 = prevpy1; + paint_or_set(!ropaque); + break; + case pL: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + if (!adjustRatio(0)) + px1 = prevpx1; + paint_or_set(!ropaque); + break; + case pR: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + if (!adjustRatio(0)) + px2 = prevpx2; + paint_or_set(!ropaque); + break; + case pINSIDE: + if (!opaque) paint_or_set(kTRUE); // draw the old box + px2 += px - dpx1 - px1; + px1 = px - dpx1; + py1 += py - dpy2 - py2; + py2 = py - dpy2; + if (px1 < px1p) { px2 += px1p - px1; px1 = px1p; } + if (px2 > px2p) { px1 -= px2 - px2p; px2 = px2p; } + if (py1 > py1p) { py2 -= py1 - py1p; py1 = py1p; } + if (py2 < py2p) { py1 += py2p - py2; py2 = py2p; } + paint_or_set(!opaque); // draw the new box + break; + } + if ((mode == pINSIDE && opaque) || (fResizing && ropaque)) { // Reset pad parameters and recompute conversion coefficients ResizePad(); - - if (pINSIDE) gPad->ShowGuidelines(this, event); - if (pTop) gPad->ShowGuidelines(this, event, 't', true); - if (pBot) gPad->ShowGuidelines(this, event, 'b', true); - if (pL) gPad->ShowGuidelines(this, event, 'l', true); - if (pR) gPad->ShowGuidelines(this, event, 'r', true); - if (pA) gPad->ShowGuidelines(this, event, '1', true); - if (pB) gPad->ShowGuidelines(this, event, '2', true); - if (pC) gPad->ShowGuidelines(this, event, '3', true); - if (pD) gPad->ShowGuidelines(this, event, '4', true); + switch(mode) { + case pINSIDE: gPad->ShowGuidelines(this, event); break; + case pTop: gPad->ShowGuidelines(this, event, 't', true); break; + case pBot: gPad->ShowGuidelines(this, event, 'b', true); break; + case pL: gPad->ShowGuidelines(this, event, 'l', true); break; + case pR: gPad->ShowGuidelines(this, event, 'r', true); break; + case pA: gPad->ShowGuidelines(this, event, '1', true); break; + case pB: gPad->ShowGuidelines(this, event, '2', true); break; + case pC: gPad->ShowGuidelines(this, event, '3', true); break; + case pD: gPad->ShowGuidelines(this, event, '4', true); break; + default: break; + } Modified(kTRUE); } @@ -2388,82 +2281,32 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) case kButton1Up: + if (opaque || ropaque) + ShowGuidelines(this, event); + if (gROOT->IsEscaped()) { gROOT->SetEscape(kFALSE); + fResizing = kFALSE; + mode = pNone; break; } - if (opaque||ropaque) { - ShowGuidelines(this, event); - } else { - x1 = x2 = y1 = y2 = 0; + if ((mode == pINSIDE && !opaque) || (fResizing && !ropaque)) { + paint_or_set(kFALSE); - if (pA) { - x1 = AbsPixeltoX(pxold); - y1 = AbsPixeltoY(pyt); - x2 = AbsPixeltoX(pxt); - y2 = AbsPixeltoY(pyold); - } - if (pB) { - x1 = AbsPixeltoX(pxl); - y1 = AbsPixeltoY(pyt); - x2 = AbsPixeltoX(pxold); - y2 = AbsPixeltoY(pyold); - } - if (pC) { - x1 = AbsPixeltoX(pxl); - y1 = AbsPixeltoY(pyold); - x2 = AbsPixeltoX(pxold); - y2 = AbsPixeltoY(pyl); - } - if (pD) { - x1 = AbsPixeltoX(pxold); - y1 = AbsPixeltoY(pyold); - x2 = AbsPixeltoX(pxt); - y2 = AbsPixeltoY(pyl); - } - if (pTop || pBot || pL || pR || pINSIDE) { - x1 = AbsPixeltoX(px1); - y1 = AbsPixeltoY(py1); - x2 = AbsPixeltoX(px2); - y2 = AbsPixeltoY(py2); - } - - if (pA || pB || pC || pD || pTop || pL || pR || pBot) + if (fResizing) Modified(kTRUE); - gVirtualX->SetLineColor(-1); - gVirtualX->SetLineWidth(-1); - - if (px != pxorg || py != pyorg) { - - // Get parent corners pixels coordinates - Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1()); - Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2()); - Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1()); - Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2()); - - // Get pad new corners pixels coordinates - Int_t apx1 = XtoAbsPixel(x1); if (apx1 < parentpx1) {apx1 = parentpx1; } - Int_t apx2 = XtoAbsPixel(x2); if (apx2 > parentpx2) {apx2 = parentpx2; } - Int_t apy1 = YtoAbsPixel(y1); if (apy1 > parentpy1) {apy1 = parentpy1; } - Int_t apy2 = YtoAbsPixel(y2); if (apy2 < parentpy2) {apy2 = parentpy2; } - - // Compute new pad positions in the NDC space of parent - fXlowNDC = Double_t(apx1 - parentpx1)/Double_t(parentpx2 - parentpx1); - fYlowNDC = Double_t(apy1 - parentpy1)/Double_t(parentpy2 - parentpy1); - fWNDC = Double_t(apx2 - apx1)/Double_t(parentpx2 - parentpx1); - fHNDC = Double_t(apy2 - apy1)/Double_t(parentpy2 - parentpy1); - } - // Reset pad parameters and recompute conversion coefficients ResizePad(); - // emit signal RangeChanged(); } + mode = pNone; + fResizing = kFALSE; + break; case kButton1Locate: @@ -2472,7 +2315,7 @@ void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py) while (true) { px = py = 0; - event = gVirtualX->RequestLocator(1, 1, px, py); + event = GetCanvasImp()->RequestLocator(px, py); ExecuteEvent(kButton1Motion, px, py); @@ -2513,7 +2356,7 @@ void TPad::ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) TView *view = GetView(); static Int_t axisNumber; static Double_t ratio1, ratio2; - static Int_t px1old, py1old, px2old, py2old; + static Double_t px1old, py1old, px2old, py2old; Int_t nbd, inc, bin1, bin2, first, last; Double_t temp, xmin,xmax; Bool_t opaque = gPad->OpaqueMoving(); @@ -2531,56 +2374,53 @@ void TPad::ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) kCont4 = kTRUE; } + auto pp = GetPainter(); + switch (event) { case kButton1Down: axisNumber = 1; - if (!strcmp(axis->GetName(),"xaxis")) { - axisNumber = 1; - if (!IsVertical()) axisNumber = 2; - } - if (!strcmp(axis->GetName(),"yaxis")) { - axisNumber = 2; - if (!IsVertical()) axisNumber = 1; - } - if (!strcmp(axis->GetName(),"zaxis")) { + if (!strcmp(axis->GetName(),"xaxis")) + axisNumber = IsVertical() ? 1 : 2; + if (!strcmp(axis->GetName(),"yaxis")) + axisNumber = IsVertical() ? 2 : 1; + if (!strcmp(axis->GetName(),"zaxis")) axisNumber = 3; - } if (view) { view->GetDistancetoAxis(axisNumber, px, py, ratio1); } else { if (axisNumber == 1) { ratio1 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin()); - px1old = XtoAbsPixel(GetUxmin()+ratio1*(GetUxmax() - GetUxmin())); - py1old = YtoAbsPixel(GetUymin()); + px1old = GetUxmin()+ratio1*(GetUxmax() - GetUxmin()); + py1old = GetUymin(); px2old = px1old; - py2old = YtoAbsPixel(GetUymax()); + py2old = GetUymax(); } else if (axisNumber == 2) { ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin()); - py1old = YtoAbsPixel(GetUymin()+ratio1*(GetUymax() - GetUymin())); - px1old = XtoAbsPixel(GetUxmin()); - px2old = XtoAbsPixel(GetUxmax()); + py1old = GetUymin()+ratio1*(GetUymax() - GetUymin()); + px1old = GetUxmin(); + px2old = GetUxmax(); py2old = py1old; } else { ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin()); - py1old = YtoAbsPixel(GetUymin()+ratio1*(GetUymax() - GetUymin())); - px1old = XtoAbsPixel(GetUxmax()); + py1old = GetUymin()+ratio1*(GetUymax() - GetUymin()); + px1old = GetUxmax(); px2old = XtoAbsPixel(GetX2()); py2old = py1old; } if (!opaque) { - gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow); + pp->DrawBox(px1old, py1old, px2old, py2old, TVirtualPadPainter::kHollow); } else { if (axisNumber == 1) { - zbx1 = AbsPixeltoX(px1old); - zbx2 = AbsPixeltoX(px2old); + zbx1 = px1old; + zbx2 = px2old; zby1 = GetUymin(); zby2 = GetUymax(); } else if (axisNumber == 2) { zbx1 = GetUxmin(); zbx2 = GetUxmax(); - zby1 = AbsPixeltoY(py1old); - zby2 = AbsPixeltoY(py2old); + zby1 = py1old; + zby2 = py2old; } if (GetLogx()) { zbx1 = TMath::Power(10,zbx1); @@ -2593,42 +2433,46 @@ void TPad::ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) zoombox = std::make_unique(zbx1, zby1, zbx2, zby2); Int_t ci = TColor::GetColor("#7d7dff"); TColor *zoomcolor = gROOT->GetColor(ci); - if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002); - else zoomcolor->SetAlpha(0.5); + if (!pp->IsSupportAlpha() || !zoomcolor) + zoombox->SetFillStyle(3002); + else + zoomcolor->SetAlpha(0.5); zoombox->SetFillColor(ci); zoombox->Draw(); gPad->Modified(); gPad->Update(); } } - if (!opaque) gVirtualX->SetLineColor(-1); + if (!opaque) + pp->SetAttLine({-1, 1, 1}); // No break !!! case kButton1Motion: if (view) { view->GetDistancetoAxis(axisNumber, px, py, ratio2); } else { - if (!opaque) gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow); + if (!opaque) + pp->DrawBox(px1old, py1old, px2old, py2old, TVirtualPadPainter::kHollow); if (axisNumber == 1) { ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin()); - px2old = XtoAbsPixel(GetUxmin()+ratio2*(GetUxmax() - GetUxmin())); + px2old = GetUxmin()+ratio2*(GetUxmax() - GetUxmin()); } else { ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin()); - py2old = YtoAbsPixel(GetUymin()+ratio2*(GetUymax() - GetUymin())); + py2old = GetUymin()+ratio2*(GetUymax() - GetUymin()); } if (!opaque) { - gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow); + pp->DrawBox(px1old, py1old, px2old, py2old, TVirtualPadPainter::kHollow); } else { if (axisNumber == 1) { - zbx1 = AbsPixeltoX(px1old); - zbx2 = AbsPixeltoX(px2old); + zbx1 = px1old; + zbx2 = px2old; zby1 = GetUymin(); zby2 = GetUymax(); } else if (axisNumber == 2) { zbx1 = GetUxmin(); zbx2 = GetUxmax(); - zby1 = AbsPixeltoY(py1old); - zby2 = AbsPixeltoY(py2old); + zby1 = py1old; + zby2 = py2old; } if (GetLogx()) { zbx1 = TMath::Power(10,zbx1); @@ -2675,7 +2519,8 @@ void TPad::ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) if (bin2>bin1) { axis->SetRange(bin1,bin2); } - if (resetAxisRange) axis->ResetBit(TAxis::kAxisRange); + if (resetAxisRange) + axis->ResetBit(TAxis::kAxisRange); if (bin2>bin1) { gPad->Modified(); gPad->Update(); @@ -2831,7 +2676,7 @@ void TPad::ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) } } if (!opaque) { - gVirtualX->SetLineColor(-1); + pp->SetAttLine({-1, 1, 1}); } else { if (zoombox) { zoombox.reset(); @@ -3784,6 +3629,9 @@ void TPad::Paint(Option_t * /*option*/) obj->Paint(lnk->GetOption()); lnk = lnk->Next(); } + + if (fCanvas && (fCanvas->fHilightPadBorder == this)) + PaintBorder(-GetHighLightColor(), kTRUE); } fPadPaint = 0; @@ -3828,99 +3676,20 @@ void TPad::PaintBorder(Color_t color, Bool_t /* tops */) if (IsTransparent()) return; - // then paint 3d frame (depending on bordermode) - // Paint a 3D frame around the pad. - if (fBorderMode == 0) return; - Int_t bordersize = fBorderSize; - if (bordersize <= 0) - bordersize = 2; - - Double_t ww = GetWw(), wh = GetWh(); - - if (!pp->IsNative()) { - // SL: need to calculate page size to get real coordiantes for border - // TODO: Code can be removed if border not need to be exact pixel size - Float_t xsize = 20, ysize = 26; - gStyle->GetPaperSize(xsize, ysize); - Double_t ratio = wh/ww; - if (xsize * ratio > ysize) - xsize = ysize/ratio; - else - ysize = xsize*ratio; - ww = 72 / 2.54 * xsize; - wh = 72 / 2.54 * ysize; - } - - const Double_t realBsX = bordersize / (GetAbsWNDC() * ww) * (fX2 - fX1); - const Double_t realBsY = bordersize / (GetAbsHNDC() * wh) * (fY2 - fY1); - - - // GetColorDark() and GetColorBright() use GetFillColor() - Color_t oldfillcolor = pp->GetFillColor(); - Color_t light = !color ? 0 : TColor::GetColorBright(color); - Color_t dark = !color ? 0 : TColor::GetColorDark(color); - - Double_t xl, xt, yl, yt; - - // Compute real left bottom & top right of the box in pixels - if (XtoPixel(fX1) < XtoPixel(fX2)) { - xl = fX1; - xt = fX2; - } else { - xl = fX2; - xt = fX1; - } - if (YtoPixel(fY1) > YtoPixel(fY2)) { - yl = fY1; - yt = fY2; - } else { - yl = fY2; - yt = fY1; - } - - Double_t frameXs[7] = {}, frameYs[7] = {}; - - // Draw top&left part of the box - frameXs[0] = xl; frameYs[0] = yl; - frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY; - frameXs[2] = frameXs[1]; frameYs[2] = yt - realBsY; - frameXs[3] = xt - realBsX; frameYs[3] = frameYs[2]; - frameXs[4] = xt; frameYs[4] = yt; - frameXs[5] = xl; frameYs[5] = yt; - frameXs[6] = xl; frameYs[6] = yl; - pp->SetFillColor(fBorderMode == -1 ? dark : light); - pp->DrawFillArea(7, frameXs, frameYs); - - // Draw bottom&right part of the box - frameXs[0] = xl; frameYs[0] = yl; - frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY; - frameXs[2] = xt - realBsX; frameYs[2] = frameYs[1]; - frameXs[3] = frameXs[2]; frameYs[3] = yt - realBsY; - frameXs[4] = xt; frameYs[4] = yt; - frameXs[5] = xt; frameYs[5] = yl; - frameXs[6] = xl; frameYs[6] = yl; - - pp->SetFillColor(fBorderMode == -1 ? light : dark); - pp->DrawFillArea(7, frameXs, frameYs); - - // If this pad is a button, highlight it - if (InheritsFrom(TButton::Class()) && fBorderMode == -1) { - if (TestBit(kFraming)) { // bit set in TButton::SetFraming - Color_t oldlinecolor = pp->GetLineColor(); - pp->SetLineColor(GetFillColor() != 2 ? 2 : 4); - pp->DrawBox(xl + realBsX, yl + realBsY, xt - realBsX, yt - realBsY, TVirtualPadPainter::kHollow); - pp->SetLineColor(oldlinecolor); - } - } - pp->SetFillColor(oldfillcolor); + // then paint 3d frame (depending on bordermode) + // Paint a 3D frame around the pad. - // No need to use PaintBorderPS, it is already performed via pad painter done! + TWbox box; + box.SetFillColor(color); + box.SetFillStyle(GetFillStyle()); + TAttLine::Copy(box); - //if (tops) - // PaintBorderPS(xl, yl, xt, yt, fBorderMode, bordersize, dark, light); + box.PaintBorderOn(this, fX1, fY1, fX2, fY2, + fBorderSize, fBorderMode, + InheritsFrom(TButton::Class()) && fBorderMode == -1 && TestBit(kFraming)); } //////////////////////////////////////////////////////////////////////////////// @@ -4099,11 +3868,14 @@ void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t pp->OnPad(this); - Int_t style0 = -1111, style = pp->GetFillStyle(); + TAttFill att = pp->GetAttFill(); + + Int_t style0 = -1111, style = att.GetFillStyle(); Bool_t draw_border = kFALSE, draw_fill = kFALSE; if (option && *option == 's') { style0 = style; - pp->SetFillStyle(0); + att.SetFillStyle(0); + pp->SetAttFill(att); style = 0; draw_border = kTRUE; } else if (option && *option == 'l') @@ -4113,7 +3885,7 @@ void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t Double_t xb[4] = {x1, x1, x2, x2}; Double_t yb[4] = {y1, y2, y2, y1}; PaintFillAreaHatches(4, xb, yb, style); - } else if (!pp->IsNative()) { + } else if (pp->GetPS()) { draw_fill = kTRUE; if (style == 0) draw_border = kFALSE; @@ -4125,11 +3897,13 @@ void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t if (style < 3026) pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled); //special case for TAttFillCanvas on real display - if (pp->GetFillColor() == 10) { + if (att.GetFillColor() == 10) { // SL: reproduce old sequence of painting calls, can have some side effects on opaque pads - pp->SetFillColor(1); + att.SetFillColor(1); + pp->SetAttFill(att); pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled); - pp->SetFillColor(10); + att.SetFillColor(10); + pp->SetAttFill(att); } } else if (style >= 4000 && style <= 4100) { // For style >=4000 we make the window transparent. @@ -4140,7 +3914,8 @@ void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t //It's clear, that virtual X checks a style (4000) and will render a hollow rect! if (pp->IsCocoa()) { style0 = style; - pp->SetFillStyle(1000); + att.SetFillStyle(1000); + pp->SetAttFill(att); } draw_fill = kTRUE; } else { @@ -4164,8 +3939,10 @@ void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t if (draw_border) pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); - if (style0 != -1111) - pp->SetFillStyle(style0); + if (style0 != -1111) { + att.SetFillStyle(style0); + pp->SetAttFill(att); + } Modified(); } @@ -4307,13 +4084,9 @@ void TPad::PaintFillAreaHatches(Int_t nn, Double_t *xx, Double_t *yy, Int_t Fill return; // Save the current line attributes and change to draw hatches - auto lws = pp->GetLineWidth(); - auto lss = pp->GetLineStyle(); - auto lcs = pp->GetLineColor(); + TAttLine saveatt = pp->GetAttLine(); - pp->SetLineStyle(1); - pp->SetLineWidth(lw); - pp->SetLineColor(pp->GetFillColor()); + pp->SetAttLine({ pp->GetAttFill().GetFillColor(), 1, lw }); // Draw the hatches if (ang1[iAng1] != 5.) @@ -4321,9 +4094,7 @@ void TPad::PaintFillAreaHatches(Int_t nn, Double_t *xx, Double_t *yy, Int_t Fill if (ang2[iAng2] != 5.) PaintHatches(dy, ang2[iAng2], nn, xx, yy); - pp->SetLineStyle(lss); - pp->SetLineWidth(lws); - pp->SetLineColor(lcs); + pp->SetAttLine(saveatt); } //////////////////////////////////////////////////////////////////////////////// @@ -4334,13 +4105,16 @@ void TPad::PaintFillAreaHatches(Int_t nn, Double_t *xx, Double_t *yy, Int_t Fill void TPad::PaintHatches(Double_t dy, Double_t angle, Int_t nn, Double_t *xx, Double_t *yy) { - Int_t i, i1, i2, nbi, m, inv; + Int_t i, i1, i2, nbi; Double_t ratiox, ratioy, ymin, ymax, yrot, ycur; const Double_t angr = TMath::Pi()*(180.-angle)/180.; const Double_t epsil = 0.0001; - const Int_t maxnbi = 100; - Double_t xli[maxnbi], yli[maxnbi], xt1, xt2, yt1, yt2; - Double_t ll, x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip; + + std::vector xli; + std::vector yli; + + Double_t xt1, xt2, yt1, yt2; + Double_t x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip; Double_t rwxmin = gPad->GetX1(); Double_t rwxmax = gPad->GetX2(); @@ -4382,14 +4156,20 @@ void TPad::PaintHatches(Double_t dy, Double_t angle, while (dy * yindx >= ymin) { ycur = dy * yindx--; nbi = 0; + + xli.clear(); + yli.clear(); + for (i=2; i<=nn+1; i++) { i2 = i; i1 = i-1; if (i == nn+1) i2=1; + x1 = wndc*ratiox*(xx[i1-1]-rwxmin); y1 = hndc*ratioy*(yy[i1-1]-rwymin); x2 = wndc*ratiox*(xx[i2-1]-rwxmin); y2 = hndc*ratioy*(yy[i2-1]-rwymin); + xt1 = cosa*x1-sina*y1; yt1 = sina*x1+cosa*y1; xt2 = cosa*x2-sina*y2; @@ -4406,8 +4186,7 @@ void TPad::PaintHatches(Double_t dy, Double_t angle, } if ((yi <= ycur) && (ycur < yip)) { nbi++; - if (nbi >= maxnbi) return; - xli[nbi-1] = xt1; + xli.push_back(xt1); } continue; } @@ -4416,11 +4195,9 @@ void TPad::PaintHatches(Double_t dy, Double_t angle, if (yt1 == yt2) { if (yt1 == ycur) { nbi++; - if (nbi >= maxnbi) return; - xli[nbi-1] = xt1; + xli.push_back(xt1); nbi++; - if (nbi >= maxnbi) return; - xli[nbi-1] = xt2; + xli.push_back(xt2); } continue; } @@ -4428,6 +4205,7 @@ void TPad::PaintHatches(Double_t dy, Double_t angle, // Other line segment a = (yt1-yt2)/(xt1-xt2); b = (yt2*xt1-xt2*yt1)/(xt1-xt2); + if (xt1 < xt2) { xi = xt1; xip = xt2; @@ -4435,47 +4213,35 @@ void TPad::PaintHatches(Double_t dy, Double_t angle, xi = xt2; xip = xt1; } + xin = (ycur-b)/a; - if ((xi <= xin) && (xin < xip) && - (TMath::Min(yt1,yt2) <= ycur) && - (ycur < TMath::Max(yt1,yt2))) { + + if ((xi <= xin) && (xin < xip) && + (TMath::Min(yt1,yt2) <= ycur) && + (ycur < TMath::Max(yt1,yt2))) { nbi++; - if (nbi >= maxnbi) return; - xli[nbi-1] = xin; + xli.push_back(xin); } } // Sorting of the x coordinates intersections - inv = 0; - m = nbi-1; -L30: - for (i=1; i<=m; i++) { - if (xli[i] < xli[i-1]) { - inv++; - ll = xli[i-1]; - xli[i-1] = xli[i]; - xli[i] = ll; - } - } - m--; - if (inv == 0) goto L50; - inv = 0; - goto L30; + std::sort(xli.begin(), xli.end()); // Draw the hatches -L50: if ((nbi%2 != 0) || (nbi == 0)) continue; for (i=0; iPaintSegments(nbi/2, xli, yli); + + gPad->PaintSegments(nbi/2, xli.data(), yli.data()); } } @@ -5310,7 +5076,7 @@ void TPad::Print(const char *filename, Option_t *option) gPad->GetCanvas()->SetHighLightColor(-1); gPad->Modified(); gPad->Update(); - if (GetPainter()){ + if (GetPainter()) { GetPainter()->SelectDrawable(wid); GetPainter()->SaveImage(this, psname.Data(), gtype); } @@ -5325,9 +5091,9 @@ void TPad::Print(const char *filename, Option_t *option) gPad->GetCanvas()->SetHighLightColor(-1); gPad->Modified(); gPad->Update(); - gVirtualX->Update(1); - gSystem->Sleep(30); // synchronize - if (GetPainter()) GetPainter()->SaveImage(this, psname, gtype); + gPad->GetCanvasImp()->UpdateDisplay(1, kTRUE); + if (GetPainter()) + GetPainter()->SaveImage(this, psname, gtype); if (!gSystem->AccessPathName(psname)) { Info("Print", "file %s has been created", psname.Data()); } @@ -5956,8 +5722,13 @@ void TPad::ResizePad(Option_t *option) fPixmapID = 0; else if (auto pp = GetPainter()) { if (pp->IsNative()) { - pp->SetLineWidth(-1); - pp->SetTextSize(-1); + // TODO: check if this is necessary + auto attl = pp->GetAttLine(); + attl.SetLineColor(-1); + pp->SetAttLine(attl); + auto attt = pp->GetAttText(); + attt.SetTextSize(-1); + pp->SetAttText(attt); // create or re-create off-screen pixmap if (fPixmapID) { int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1)); @@ -6400,10 +6171,8 @@ void TPad::SetView(TView *view) void TPad::SetAttFillPS(Color_t color, Style_t style) { if (auto pp = GetPainter()) - if (!pp->IsNative()) { - pp->SetFillColor(color); - pp->SetFillStyle(style); - } + if (pp->GetPS()) + pp->SetAttFill({color, style}); } //////////////////////////////////////////////////////////////////////////////// @@ -6414,11 +6183,8 @@ void TPad::SetAttFillPS(Color_t color, Style_t style) void TPad::SetAttLinePS(Color_t color, Style_t style, Width_t lwidth) { if (auto pp = GetPainter()) - if (!pp->IsNative()) { - pp->SetLineColor(color); - pp->SetLineStyle(style); - pp->SetLineWidth(lwidth); - } + if (pp->GetPS()) + pp->SetAttLine({color, style, lwidth}); } //////////////////////////////////////////////////////////////////////////////// @@ -6429,11 +6195,8 @@ void TPad::SetAttLinePS(Color_t color, Style_t style, Width_t lwidth) void TPad::SetAttMarkerPS(Color_t color, Style_t style, Size_t msize) { if (auto pp = GetPainter()) - if (!pp->IsNative()) { - pp->SetMarkerColor(color); - pp->SetMarkerStyle(style); - pp->SetMarkerSize(msize); - } + if (pp->GetPS()) + pp->SetAttMarker({color, style, msize}); } //////////////////////////////////////////////////////////////////////////////// @@ -6444,13 +6207,8 @@ void TPad::SetAttMarkerPS(Color_t color, Style_t style, Size_t msize) void TPad::SetAttTextPS(Int_t align, Float_t angle, Color_t color, Style_t font, Float_t tsize) { if (auto pp = GetPainter()) - if (!pp->IsNative()) { - pp->SetTextAlign(align); - pp->SetTextAngle(angle); - pp->SetTextColor(color); - pp->SetTextFont(font); - - if (font%10 > 2) { + if (pp->GetPS()) { + if (font % 10 > 2) { Float_t wh = (Float_t) XtoPixel(GetX2()); Float_t hh = (Float_t) YtoPixel(GetY1()); Float_t dy; @@ -6462,7 +6220,7 @@ void TPad::SetAttTextPS(Int_t align, Float_t angle, Color_t color, Style_t font, tsize = dy/(GetY2()-GetY1()); } } - pp->SetTextSize(tsize); + pp->SetAttText({align, angle, color, font, tsize}); } } diff --git a/graf2d/gpad/src/TPadPainter.cxx b/graf2d/gpad/src/TPadPainter.cxx index 41dd510269633..491c00c4bd315 100644 --- a/graf2d/gpad/src/TPadPainter.cxx +++ b/graf2d/gpad/src/TPadPainter.cxx @@ -47,13 +47,13 @@ void ConvertPointsAndMergePassX(TVirtualPad *pad, unsigned nPoints, const T *x, void ConvertPointsAndMergeInplacePassY(std::vector &dst); template -void DrawFillAreaAux(TVirtualPad *pad, Int_t nPoints, const T *xs, const T *ys); +void DrawFillAreaAux(TVirtualPad *pad, WinContext_t cont, Int_t nPoints, const T *xs, const T *ys, Bool_t close_path); template -void DrawPolyLineAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys); +void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, unsigned nPoints, const T *xs, const T *ys); template -void DrawPolyMarkerAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys); +void DrawPolyMarkerAux(TVirtualPad *pad, WinContext_t cont, unsigned nPoints, const T *xs, const T *ys); } @@ -70,6 +70,8 @@ Implement TVirtualPadPainter which abstracts painting operations. TPadPainter::TPadPainter() { + fDoubleBuffer = 1; + fWinContext = (WinContext_t) 0; } /* @@ -82,106 +84,6 @@ gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualX. */ -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Color_t TPadPainter::GetLineColor() const -{ - return gVirtualX->GetLineColor(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Style_t TPadPainter::GetLineStyle() const -{ - return gVirtualX->GetLineStyle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Width_t TPadPainter::GetLineWidth() const -{ - return gVirtualX->GetLineWidth(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TPadPainter::SetLineColor(Color_t lcolor) -{ - gVirtualX->SetLineColor(lcolor); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TPadPainter::SetLineStyle(Style_t lstyle) -{ - gVirtualX->SetLineStyle(lstyle); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TPadPainter::SetLineWidth(Width_t lwidth) -{ - gVirtualX->SetLineWidth(lwidth); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Color_t TPadPainter::GetFillColor() const -{ - return gVirtualX->GetFillColor(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Style_t TPadPainter::GetFillStyle() const -{ - return gVirtualX->GetFillStyle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Bool_t TPadPainter::IsTransparent() const -{ - //IsTransparent is implemented as inline function in TAttFill. - return gVirtualX->IsTransparent(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TPadPainter::SetFillColor(Color_t fcolor) -{ - gVirtualX->SetFillColor(fcolor); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TPadPainter::SetFillStyle(Style_t fstyle) -{ - gVirtualX->SetFillStyle(fstyle); -} - - //////////////////////////////////////////////////////////////////////////////// /// Delegate to gVirtualX. @@ -190,52 +92,6 @@ void TPadPainter::SetOpacity(Int_t percent) gVirtualX->SetOpacity(percent); } - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Short_t TPadPainter::GetTextAlign() const -{ - return gVirtualX->GetTextAlign(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Float_t TPadPainter::GetTextAngle() const -{ - return gVirtualX->GetTextAngle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Color_t TPadPainter::GetTextColor() const -{ - return gVirtualX->GetTextColor(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Font_t TPadPainter::GetTextFont() const -{ - return gVirtualX->GetTextFont(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Float_t TPadPainter::GetTextSize() const -{ - return gVirtualX->GetTextSize(); -} - - //////////////////////////////////////////////////////////////////////////////// /// Delegate to gVirtualX. @@ -244,198 +100,165 @@ Float_t TPadPainter::GetTextMagnitude() const return gVirtualX->GetTextMagnitude(); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Create a gVirtualX Pixmap. -void TPadPainter::SetTextAlign(Short_t align) +Int_t TPadPainter::CreateDrawable(UInt_t w, UInt_t h) { - gVirtualX->SetTextAlign(align); + return gVirtualX->OpenPixmap(Int_t(w), Int_t(h)); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Resize a gVirtualX Pixmap. -void TPadPainter::SetTextAngle(Float_t tangle) +Int_t TPadPainter::ResizeDrawable(Int_t device, UInt_t w, UInt_t h) { - gVirtualX->SetTextAngle(tangle); + return gVirtualX->ResizePixmap(device, w, h); } //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Returns true when cocoa backend is used -void TPadPainter::SetTextColor(Color_t tcolor) +Bool_t TPadPainter::IsCocoa() const { - gVirtualX->SetTextColor(tcolor); + return gVirtualX->InheritsFrom("TGCocoa"); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Returns true if trasnparent colors are supported -void TPadPainter::SetTextFont(Font_t tfont) +Bool_t TPadPainter::IsSupportAlpha() const { - gVirtualX->SetTextFont(tfont); + return gVirtualX->InheritsFrom("TGQuartz"); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Clear the current gVirtualX window. -void TPadPainter::SetTextSize(Float_t tsize) +void TPadPainter::ClearDrawable() { - gVirtualX->SetTextSize(tsize); + gVirtualX->ClearWindowW(fWinContext); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Copy a gVirtualX pixmap. -void TPadPainter::SetTextSizePixels(Int_t npixels) +void TPadPainter::CopyDrawable(Int_t device, Int_t px, Int_t py) { - gVirtualX->SetTextSizePixels(npixels); + gVirtualX->CopyPixmap(device, px, py); } //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Close the current gVirtualX pixmap. -Color_t TPadPainter::GetMarkerColor() const +void TPadPainter::DestroyDrawable(Int_t device) { - return gVirtualX->GetMarkerColor(); + gVirtualX->SelectWindow(device); + gVirtualX->ClosePixmap(); + fWinContext = (WinContext_t) 0; } //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Select the window in which the graphics will go. -Style_t TPadPainter::GetMarkerStyle() const +void TPadPainter::SelectDrawable(Int_t device) { - return gVirtualX->GetMarkerStyle(); + gVirtualX->SelectWindow(device); + fWinContext = gVirtualX->GetWindowContext(device); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Call low-level update of selected drawable, redirect to gVirtualX. -Size_t TPadPainter::GetMarkerSize() const +void TPadPainter::UpdateDrawable(Int_t mode) { - return gVirtualX->GetMarkerSize(); + gVirtualX->UpdateWindowW(fWinContext, mode); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Set drawing mode for specified device -void TPadPainter::SetMarkerColor(Color_t mcolor) +void TPadPainter::SetDrawMode(Int_t device, Int_t mode) { - gVirtualX->SetMarkerColor(mcolor); + gVirtualX->SetDrawModeW(gVirtualX->GetWindowContext(device), (TVirtualX::EDrawMode) mode); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Set double buffer mode for specified device -void TPadPainter::SetMarkerStyle(Style_t mstyle) +void TPadPainter::SetDoubleBuffer(Int_t device, Int_t mode) { - gVirtualX->SetMarkerStyle(mstyle); -} + // important flag - when disabled canvas pixmap used directly + // so one need to use absolute coordinates + fDoubleBuffer = mode; - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TPadPainter::SetMarkerSize(Size_t msize) -{ - gVirtualX->SetMarkerSize(msize); + gVirtualX->SetDoubleBuffer(device, mode); } - //////////////////////////////////////////////////////////////////////////////// -/// Create a gVirtualX Pixmap. +///Noop, for non-gl pad TASImage calls gVirtualX->CopyArea. -Int_t TPadPainter::CreateDrawable(UInt_t w, UInt_t h) +void TPadPainter::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*width*/, UInt_t /*height*/, + Int_t /*dstX*/, Int_t /*dstY*/, Bool_t /*enableAlphaBlending*/) { - return gVirtualX->OpenPixmap(Int_t(w), Int_t(h)); } //////////////////////////////////////////////////////////////////////////////// -/// Resize a gVirtualX Pixmap. +/// Set fill attributes -Int_t TPadPainter::ResizeDrawable(Int_t device, UInt_t w, UInt_t h) +void TPadPainter::SetAttFill(const TAttFill &att) { - return gVirtualX->ResizePixmap(device, w, h); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Returns true when cocoa backend is used + TPadPainterBase::SetAttFill(att); -Bool_t TPadPainter::IsCocoa() const -{ - return gVirtualX->InheritsFrom("TGCocoa"); + gVirtualX->SetAttFill(fWinContext, att); } - //////////////////////////////////////////////////////////////////////////////// -/// Clear the current gVirtualX window. +/// Set line attributes -void TPadPainter::ClearDrawable() +void TPadPainter::SetAttLine(const TAttLine &att) { - gVirtualX->ClearWindow(); -} + TPadPainterBase::SetAttLine(att); - -//////////////////////////////////////////////////////////////////////////////// -/// Copy a gVirtualX pixmap. - -void TPadPainter::CopyDrawable(Int_t device, Int_t px, Int_t py) -{ - gVirtualX->CopyPixmap(device, px, py); + gVirtualX->SetAttLine(fWinContext, att); } - //////////////////////////////////////////////////////////////////////////////// -/// Close the current gVirtualX pixmap. +/// Set marker attributes -void TPadPainter::DestroyDrawable(Int_t device) +void TPadPainter::SetAttMarker(const TAttMarker &att) { - gVirtualX->SelectWindow(device); - gVirtualX->ClosePixmap(); -} + TPadPainterBase::SetAttMarker(att); - -//////////////////////////////////////////////////////////////////////////////// -/// Select the window in which the graphics will go. - -void TPadPainter::SelectDrawable(Int_t device) -{ - gVirtualX->SelectWindow(device); + gVirtualX->SetAttMarker(fWinContext, att); } //////////////////////////////////////////////////////////////////////////////// -///Noop, for non-gl pad TASImage calls gVirtualX->CopyArea. +/// Set text attributes -void TPadPainter::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*width*/, UInt_t /*height*/, - Int_t /*dstX*/, Int_t /*dstY*/, Bool_t /*enableAlphaBlending*/) +void TPadPainter::SetAttText(const TAttText &att) { -} + TPadPainterBase::SetAttText(att); + gVirtualX->SetAttText(fWinContext, att); +} //////////////////////////////////////////////////////////////////////////////// /// Paint a simple line. void TPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) { - if (GetLineWidth()<=0) return; + if (fAttLine.GetLineWidth() <= 0) + return; - const Int_t px1 = gPad->XtoPixel(x1); - const Int_t px2 = gPad->XtoPixel(x2); - const Int_t py1 = gPad->YtoPixel(y1); - const Int_t py2 = gPad->YtoPixel(y2); - gVirtualX->DrawLine(px1, py1, px2, py2); + const Int_t px1 = fDoubleBuffer ? gPad->XtoPixel(x1) : gPad->XtoAbsPixel(x1); + const Int_t px2 = fDoubleBuffer ? gPad->XtoPixel(x2) : gPad->XtoAbsPixel(x2); + const Int_t py1 = fDoubleBuffer ? gPad->YtoPixel(y1) : gPad->YtoAbsPixel(y1); + const Int_t py2 = fDoubleBuffer ? gPad->YtoPixel(y2) : gPad->YtoAbsPixel(y2); + gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2); } @@ -444,13 +267,14 @@ void TPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) void TPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) { - if (GetLineWidth()<=0) return; + if (fAttLine.GetLineWidth() <= 0) + return; - const Int_t px1 = gPad->UtoPixel(u1); - const Int_t py1 = gPad->VtoPixel(v1); - const Int_t px2 = gPad->UtoPixel(u2); - const Int_t py2 = gPad->VtoPixel(v2); - gVirtualX->DrawLine(px1, py1, px2, py2); + const Int_t px1 = fDoubleBuffer ? gPad->UtoPixel(u1) : gPad->UtoAbsPixel(u1); + const Int_t py1 = fDoubleBuffer ? gPad->VtoPixel(v1) : gPad->VtoAbsPixel(v1); + const Int_t px2 = fDoubleBuffer ? gPad->UtoPixel(u2) : gPad->UtoAbsPixel(u2); + const Int_t py2 = fDoubleBuffer ? gPad->VtoPixel(v2) : gPad->VtoAbsPixel(v2); + gVirtualX->DrawLineW(fWinContext, px1, py1, px2, py2); } @@ -459,12 +283,13 @@ void TPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2 void TPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) { - if (GetLineWidth()<=0 && mode == TVirtualPadPainter::kHollow) return; + if (fAttLine.GetLineWidth() <= 0 && mode == TVirtualPadPainter::kHollow) + return; - Int_t px1 = gPad->XtoPixel(x1); - Int_t px2 = gPad->XtoPixel(x2); - Int_t py1 = gPad->YtoPixel(y1); - Int_t py2 = gPad->YtoPixel(y2); + Int_t px1 = fDoubleBuffer ? gPad->XtoPixel(x1) : gPad->XtoAbsPixel(x1); + Int_t px2 = fDoubleBuffer ? gPad->XtoPixel(x2) : gPad->XtoAbsPixel(x2); + Int_t py1 = fDoubleBuffer ? gPad->YtoPixel(y1) : gPad->YtoAbsPixel(y1); + Int_t py2 = fDoubleBuffer ? gPad->YtoPixel(y2) : gPad->YtoAbsPixel(y2); // Box width must be at least one pixel (WTF is this code???) if (TMath::Abs(px2 - px1) < 1) @@ -472,7 +297,7 @@ void TPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EB if (TMath::Abs(py1 - py2) < 1) py1 = py2 + 1; - gVirtualX->DrawBox(px1, py1, px2, py2, (TVirtualX::EBoxMode)mode); + gVirtualX->DrawBoxW(fWinContext, px1, py1, px2, py2, (TVirtualX::EBoxMode)mode); } //////////////////////////////////////////////////////////////////////////////// @@ -485,7 +310,7 @@ void TPadPainter::DrawFillArea(Int_t nPoints, const Double_t *xs, const Double_t return; } - DrawFillAreaAux(gPad, nPoints, xs, ys); + DrawFillAreaAux(gPad, fWinContext, nPoints, xs, ys, fAttFill.GetFillStyle() == 0); } @@ -499,7 +324,7 @@ void TPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t * return; } - DrawFillAreaAux(gPad, nPoints, xs, ys); + DrawFillAreaAux(gPad, fWinContext, nPoints, xs, ys, fAttFill.GetFillStyle() == 0); } //////////////////////////////////////////////////////////////////////////////// @@ -507,14 +332,15 @@ void TPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t * void TPadPainter::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys) { - if (GetLineWidth()<=0) return; + if (fAttLine.GetLineWidth() <= 0) + return; if (n < 2) { ::Error("TPadPainter::DrawPolyLine", "invalid number of points"); return; } - DrawPolyLineAux(gPad, n, xs, ys); + DrawPolyLineAux(gPad, fWinContext, n, xs, ys); } @@ -523,14 +349,15 @@ void TPadPainter::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys) void TPadPainter::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys) { - if (GetLineWidth()<=0) return; + if (fAttLine.GetLineWidth() <= 0) + return; if (n < 2) { ::Error("TPadPainter::DrawPolyLine", "invalid number of points"); return; } - DrawPolyLineAux(gPad, n, xs, ys); + DrawPolyLineAux(gPad, fWinContext, n, xs, ys); } @@ -539,7 +366,8 @@ void TPadPainter::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys) void TPadPainter::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) { - if (GetLineWidth()<=0) return; + if (fAttLine.GetLineWidth() <= 0) + return; if (n < 2) { ::Error("TPadPainter::DrawPolyLineNDC", "invalid number of points %d", n); @@ -553,7 +381,7 @@ void TPadPainter::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) xy[i].fY = (SCoord_t)gPad->VtoPixel(v[i]); } - gVirtualX->DrawPolyLine(n, &xy[0]); + gVirtualX->DrawPolyLineW(fWinContext, n, &xy[0]); } //////////////////////////////////////////////////////////////////////////////// @@ -561,7 +389,7 @@ void TPadPainter::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) void TPadPainter::DrawSegments(Int_t n, Double_t *x, Double_t *y) { - if (GetLineWidth() <= 0) + if (fAttLine.GetLineWidth() <= 0) return; if (n < 1) { @@ -584,7 +412,7 @@ void TPadPainter::DrawSegments(Int_t n, Double_t *x, Double_t *y) } if (cnt > 1) - gVirtualX->DrawLinesSegments(cnt/2, &xy[0]); + gVirtualX->DrawLinesSegmentsW(fWinContext, cnt/2, &xy[0]); } //////////////////////////////////////////////////////////////////////////////// @@ -592,7 +420,7 @@ void TPadPainter::DrawSegments(Int_t n, Double_t *x, Double_t *y) void TPadPainter::DrawSegmentsNDC(Int_t n, Double_t *u, Double_t *v) { - if (GetLineWidth() <= 0) + if (fAttLine.GetLineWidth() <= 0) return; if (n < 1) { @@ -615,7 +443,7 @@ void TPadPainter::DrawSegmentsNDC(Int_t n, Double_t *u, Double_t *v) } if (cnt > 1) - gVirtualX->DrawLinesSegments(cnt/2, &xy[0]); + gVirtualX->DrawLinesSegmentsW(fWinContext, cnt/2, &xy[0]); } @@ -630,7 +458,7 @@ void TPadPainter::DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y) return; } - DrawPolyMarkerAux(gPad, n, x, y); + DrawPolyMarkerAux(gPad, fWinContext, n, x, y); } @@ -644,7 +472,7 @@ void TPadPainter::DrawPolyMarker(Int_t n, const Float_t *x, const Float_t *y) return; } - DrawPolyMarkerAux(gPad, n, x, y); + DrawPolyMarkerAux(gPad, fWinContext, n, x, y); } @@ -657,7 +485,7 @@ void TPadPainter::DrawText(Double_t x, Double_t y, const char *text, ETextMode m const Int_t py = gPad->YtoPixel(y); const Double_t angle = GetTextAngle(); const Double_t mgn = GetTextMagnitude(); - gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); + gVirtualX->DrawTextW(fWinContext, px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); } @@ -670,7 +498,7 @@ void TPadPainter::DrawText(Double_t x, Double_t y, const wchar_t *text, ETextMod const Int_t py = gPad->YtoPixel(y); const Double_t angle = GetTextAngle(); const Double_t mgn = GetTextMagnitude(); - gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); + gVirtualX->DrawTextW(fWinContext, px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); } @@ -683,7 +511,7 @@ void TPadPainter::DrawTextNDC(Double_t u, Double_t v, const char *text, ETextMod const Int_t py = gPad->VtoPixel(v); const Double_t angle = GetTextAngle(); const Double_t mgn = GetTextMagnitude(); - gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); + gVirtualX->DrawTextW(fWinContext, px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); } @@ -759,7 +587,7 @@ void TPadPainter::DrawTextNDC(Double_t u, Double_t v, const wchar_t *text, EText const Int_t py = gPad->VtoPixel(v); const Double_t angle = GetTextAngle(); const Double_t mgn = GetTextMagnitude(); - gVirtualX->DrawText(px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); + gVirtualX->DrawTextW(fWinContext, px, py, angle, mgn, text, (TVirtualX::ETextMode)mode); } //Aux. private functions. @@ -962,7 +790,7 @@ void ConvertPointsAndMerge(TVirtualPad *pad, unsigned threshold, unsigned nPoint //////////////////////////////////////////////////////////////////////////////// template -void DrawFillAreaAux(TVirtualPad *pad, Int_t nPoints, const T *xs, const T *ys) +void DrawFillAreaAux(TVirtualPad *pad, WinContext_t cont, Int_t nPoints, const T *xs, const T *ys, Bool_t close_path) { std::vector xy; @@ -981,19 +809,19 @@ void DrawFillAreaAux(TVirtualPad *pad, Int_t nPoints, const T *xs, const T *ys) ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy); //We close the 'polygon' and it'll be rendered as a polyline by gVirtualX. - if (!gVirtualX->GetFillStyle()) + if (close_path) xy.push_back(xy.front()); if (xy.size() > 2) - gVirtualX->DrawFillArea(xy.size(), &xy[0]); + gVirtualX->DrawFillAreaW(cont, xy.size(), &xy[0]); } //////////////////////////////////////////////////////////////////////////////// template -void DrawPolyLineAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys) +void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, unsigned nPoints, const T *xs, const T *ys) { - std::vector xy; + std::vector xy; const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(), pad->GetWh() * pad->GetAbsHNDC())) * 2; @@ -1009,14 +837,14 @@ void DrawPolyLineAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *y ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy); if (xy.size() > 1) - gVirtualX->DrawPolyLine(xy.size(), &xy[0]); + gVirtualX->DrawPolyLineW(cont, xy.size(), &xy[0]); } //////////////////////////////////////////////////////////////////////////////// template -void DrawPolyMarkerAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys) +void DrawPolyMarkerAux(TVirtualPad *pad, WinContext_t cont, unsigned nPoints, const T *xs, const T *ys) { std::vector xy(nPoints); @@ -1025,7 +853,7 @@ void DrawPolyMarkerAux(TVirtualPad *pad, unsigned nPoints, const T *xs, const T xy[i].fY = (SCoord_t)pad->YtoPixel(ys[i]); } - gVirtualX->DrawPolyMarker(nPoints, &xy[0]); + gVirtualX->DrawPolyMarkerW(cont, nPoints, &xy[0]); } } diff --git a/graf2d/gpad/src/TPadPainterPS.cxx b/graf2d/gpad/src/TPadPainterPS.cxx index 4c73198087629..0b5a10d80b52e 100644 --- a/graf2d/gpad/src/TPadPainterPS.cxx +++ b/graf2d/gpad/src/TPadPainterPS.cxx @@ -46,110 +46,12 @@ many of them are set by base sub-objects of 2d primitives (2d primitives usually inherit TAttLine or TAttFill etc.). And these sub-objects call gVirtualPS->SetLineWidth ... etc. So, if I save some attributes in my painter, it will be mess - at any moment I do not know, where to take line attribute - from -gVirtualX or from my own member. So! All attributed, _ALL_ go to/from gVirtualPS. +gVirtualX or from my own member. So! All attributed, _ALL_ go to gVirtualPS. +At the same time attributes copy preserved in the painter - +so actual value can be requested without asking of gVirtualPS instance */ -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Color_t TPadPainterPS::GetLineColor() const -{ - return fPS->GetLineColor(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Style_t TPadPainterPS::GetLineStyle() const -{ - return fPS->GetLineStyle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Width_t TPadPainterPS::GetLineWidth() const -{ - return fPS->GetLineWidth(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetLineColor(Color_t lcolor) -{ - fPS->SetLineColor(lcolor); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetLineStyle(Style_t lstyle) -{ - fPS->SetLineStyle(lstyle); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetLineWidth(Width_t lwidth) -{ - fPS->SetLineWidth(lwidth); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Color_t TPadPainterPS::GetFillColor() const -{ - return fPS->GetFillColor(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Style_t TPadPainterPS::GetFillStyle() const -{ - return fPS->GetFillStyle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Bool_t TPadPainterPS::IsTransparent() const -{ - //IsTransparent is implemented as inline function in TAttFill. - return fPS->IsTransparent(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetFillColor(Color_t fcolor) -{ - fPS->SetFillColor(fcolor); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetFillStyle(Style_t fstyle) -{ - fPS->SetFillStyle(fstyle); -} - - //////////////////////////////////////////////////////////////////////////////// /// Delegate to gVirtualPS. @@ -158,167 +60,53 @@ void TPadPainterPS::SetOpacity(Int_t percent) fPS->SetFillStyle(4000 + percent); } - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Short_t TPadPainterPS::GetTextAlign() const -{ - return fPS->GetTextAlign(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Float_t TPadPainterPS::GetTextAngle() const -{ - return fPS->GetTextAngle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Color_t TPadPainterPS::GetTextColor() const -{ - return fPS->GetTextColor(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Font_t TPadPainterPS::GetTextFont() const -{ - return fPS->GetTextFont(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Float_t TPadPainterPS::GetTextSize() const -{ - return fPS->GetTextSize(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Float_t TPadPainterPS::GetTextMagnitude() const -{ - // FIXME!!! - return 0; -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetTextAlign(Short_t align) -{ - fPS->SetTextAlign(align); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetTextAngle(Float_t tangle) -{ - fPS->SetTextAngle(tangle); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetTextColor(Color_t tcolor) -{ - fPS->SetTextColor(tcolor); -} - - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. +/// Provide fill attributes to gVirtualPS. -void TPadPainterPS::SetTextFont(Font_t tfont) +void TPadPainterPS::SetAttFill(const TAttFill &att) { - fPS->SetTextFont(tfont); -} + TPadPainterBase::SetAttFill(att); - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetTextSize(Float_t tsize) -{ - fPS->SetTextSize(tsize); + fPS->SetFillColor(att.GetFillColor()); + fPS->SetFillStyle(att.GetFillStyle()); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. +/// Provide line attributes to gVirtualPS. -void TPadPainterPS::SetTextSizePixels(Int_t npixels) +void TPadPainterPS::SetAttLine(const TAttLine &att) { - fPS->SetTextSizePixels(npixels); -} - + TPadPainterBase::SetAttLine(att); -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Color_t TPadPainterPS::GetMarkerColor() const -{ - return fPS->GetMarkerColor(); + fPS->SetLineColor(att.GetLineColor()); + fPS->SetLineStyle(att.GetLineStyle()); + fPS->SetLineWidth(att.GetLineWidth()); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. +/// Provide marker attributes to gVirtualPS. -Style_t TPadPainterPS::GetMarkerStyle() const +void TPadPainterPS::SetAttMarker(const TAttMarker &att) { - return fPS->GetMarkerStyle(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -Size_t TPadPainterPS::GetMarkerSize() const -{ - return fPS->GetMarkerSize(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. + TPadPainterBase::SetAttMarker(att); -void TPadPainterPS::SetMarkerColor(Color_t mcolor) -{ - fPS->SetMarkerColor(mcolor); + fPS->SetMarkerColor(att.GetMarkerColor()); + fPS->SetMarkerSize(att.GetMarkerSize()); + fPS->SetMarkerStyle(att.GetMarkerStyle()); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. +/// Provide text attributes to gVirtualPS. -void TPadPainterPS::SetMarkerStyle(Style_t mstyle) +void TPadPainterPS::SetAttText(const TAttText &att) { - fPS->SetMarkerStyle(mstyle); -} + TPadPainterBase::SetAttText(att); - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualPS. - -void TPadPainterPS::SetMarkerSize(Size_t msize) -{ - fPS->SetMarkerSize(msize); + fPS->SetTextAlign(att.GetTextAlign()); + fPS->SetTextAngle(att.GetTextAngle()); + fPS->SetTextColor(att.GetTextColor()); + fPS->SetTextSize(att.GetTextSize()); + fPS->SetTextFont(att.GetTextFont()); } @@ -387,7 +175,7 @@ void TPadPainterPS::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*wid void TPadPainterPS::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; Double_t x[2] = {x1, x2}, y[2] = {y1, y2}; fPS->DrawPS(2, x, y); @@ -399,7 +187,7 @@ void TPadPainterPS::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) void TPadPainterPS::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; Double_t xw[2], yw[2]; @@ -420,7 +208,7 @@ void TPadPainterPS::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Int_t style0 = -1; if (mode == TVirtualPadPainter::kHollow) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; style0 = fPS->GetFillStyle(); if (style0 > 0) @@ -465,7 +253,7 @@ void TPadPainterPS::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t void TPadPainterPS::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; if (n < 2) { @@ -482,7 +270,7 @@ void TPadPainterPS::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys void TPadPainterPS::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; if (n < 2) { @@ -499,7 +287,7 @@ void TPadPainterPS::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys) void TPadPainterPS::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; if (n < 2) { @@ -520,7 +308,7 @@ void TPadPainterPS::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t * void TPadPainterPS::DrawSegments(Int_t n, Double_t *x, Double_t *y) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; if (n < 1) { @@ -536,7 +324,7 @@ void TPadPainterPS::DrawSegments(Int_t n, Double_t *x, Double_t *y) void TPadPainterPS::DrawSegmentsNDC(Int_t n, Double_t *u, Double_t *v) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; if (n < 1) { diff --git a/graf2d/graf/CMakeLists.txt b/graf2d/graf/CMakeLists.txt index d7d1b77c21a61..f7a0f9703723e 100644 --- a/graf2d/graf/CMakeLists.txt +++ b/graf2d/graf/CMakeLists.txt @@ -88,7 +88,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Graf DICTIONARY_OPTIONS -writeEmptyRootPCM LIBRARIES - ${FREETYPE_LIBRARIES} + Freetype::Freetype ZLIB::ZLIB mathtext DEPENDENCIES @@ -99,5 +99,3 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Graf BUILTINS FREETYPE ) - -target_include_directories(Graf PRIVATE ${FREETYPE_INCLUDE_DIRS}) diff --git a/graf2d/graf/inc/TWbox.h b/graf2d/graf/inc/TWbox.h index 1890643c8178f..c194f3eb36e93 100644 --- a/graf2d/graf/inc/TWbox.h +++ b/graf2d/graf/inc/TWbox.h @@ -42,6 +42,9 @@ class TWbox : public TBox { Int_t GetDarkColor() const {return TColor::GetColorDark(GetFillColor());} Int_t GetLightColor() const {return TColor::GetColorBright(GetFillColor());} void Paint(Option_t *option="") override; + void PaintBorderOn(TVirtualPad *pad, + Double_t x1, Double_t y1,Double_t x2 ,Double_t y2, + Short_t bordersize, Short_t bordermode, Bool_t with_selection = kFALSE); virtual void PaintFrame(Double_t x1, Double_t y1,Double_t x2 ,Double_t y2, Color_t color, Short_t bordersize, Short_t bordermode, Bool_t tops); diff --git a/graf2d/graf/src/TArrow.cxx b/graf2d/graf/src/TArrow.cxx index 1138b1d35d5b7..85dd8ad19236b 100644 --- a/graf2d/graf/src/TArrow.cxx +++ b/graf2d/graf/src/TArrow.cxx @@ -13,8 +13,7 @@ #include "TMath.h" #include "TArrow.h" #include "TVirtualPad.h" -#include "TVirtualPS.h" -#include "TVirtualX.h" +#include "TVirtualPadPainter.h" Float_t TArrow::fgDefaultAngle = 60; Float_t TArrow::fgDefaultArrowSize = 0.05; @@ -117,9 +116,7 @@ void TArrow::Copy(TObject &obj) const void TArrow::Draw(Option_t *option) { - Option_t *opt; - if (option && strlen(option)) opt = option; - else opt = (char*)GetOption(); + Option_t *opt = option && *option ? option : GetOption(); AppendPad(opt); } @@ -131,15 +128,15 @@ void TArrow::Draw(Option_t *option) /// - if `option=""`, `option` will be the current arrow option TArrow *TArrow::DrawArrow(Double_t x1, Double_t y1,Double_t x2, Double_t y2, - Float_t arrowsize ,Option_t *option) + Float_t arrowsize, Option_t *option) { Float_t size = arrowsize; if (size <= 0) size = fArrowSize; if (size <= 0) size = 0.05; - const char* opt = option; - if (!opt || !opt[0]) opt = fOption.Data(); - if (!opt || !opt[0]) opt = "|>"; + Option_t* opt = option; + if (!opt || !*opt) opt = GetOption(); + if (!opt || !*opt) opt = "|>"; TArrow *newarrow = new TArrow(x1,y1,x2,y2,size,opt); newarrow->SetAngle(fAngle); TAttLine::Copy(*newarrow); @@ -155,14 +152,9 @@ TArrow *TArrow::DrawArrow(Double_t x1, Double_t y1,Double_t x2, Double_t y2, void TArrow::Paint(Option_t *option) { if (!gPad) return; - Option_t *opt; - if (option && strlen(option)) opt = option; - else opt = (char*)GetOption(); + Option_t *opt = option && *option ? option : GetOption(); if (TestBit(kLineNDC)) - PaintArrow(gPad->GetX1() + fX1 * (gPad->GetX2() - gPad->GetX1()), - gPad->GetY1() + fY1 * (gPad->GetY2() - gPad->GetY1()), - gPad->GetX1() + fX2 * (gPad->GetX2() - gPad->GetX1()), - gPad->GetY1() + fY2 * (gPad->GetY2() - gPad->GetY1()), fArrowSize, opt); + PaintArrowNDC(fX1, fY1, fX2, fY2, fArrowSize, opt); else PaintArrow(gPad->XtoPad(fX1), gPad->YtoPad(fY1), gPad->XtoPad(fX2), gPad->YtoPad(fY2), fArrowSize, opt); } @@ -174,11 +166,12 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Float_t arrowsize, Option_t *option) { if (!gPad) return; + auto &parent = *gPad; // Compute the gPad coordinates in TRUE normalized space (NDC) - Int_t iw = gPad->GetWw(); - Int_t ih = gPad->GetWh(); + Int_t iw = parent.GetWw(); + Int_t ih = parent.GetWh(); Double_t x1p,y1p,x2p,y2p; - gPad->GetPadPar(x1p,y1p,x2p,y2p); + parent.GetPadPar(x1p,y1p,x2p,y2p); Int_t ix1 = (Int_t)(iw*x1p); Int_t iy1 = (Int_t)(ih*y1p); Int_t ix2 = (Int_t)(iw*x2p); @@ -188,8 +181,8 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, // Option and attributes TString opt = option; opt.ToLower(); - TAttLine::Modify(); - TAttFill::Modify(); + TAttLine::ModifyOn(parent); + TAttFill::ModifyOn(parent); Double_t wndc = TMath::Min(1.,(Double_t)iw/(Double_t)ih); @@ -203,7 +196,7 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, // Ratios to convert user space in TRUE normalized space (NDC) Double_t rx1,ry1,rx2,ry2; - gPad->GetRange(rx1,ry1,rx2,ry2); + parent.GetRange(rx1,ry1,rx2,ry2); Double_t rx = (x2ndc-x1ndc)/(rx2-rx1); Double_t ry = (y2ndc-y1ndc)/(ry2-ry1); @@ -275,7 +268,7 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, yarr[i] = (1/ry)*(yarr[i]-y1ndc)+ry1; } // paint arrow main line with start/stop segment together - gPad->PaintSegments(cnt/2, xarr, yarr); + parent.PaintSegments(cnt/2, xarr, yarr); // Draw the arrow's head(s) if (opt.Contains(">")) { @@ -296,16 +289,15 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, y2ar[i] = (1/ry)*(y2ar[i]-y1ndc)+ry1; } if (opt.Contains("|>")) { - if (gVirtualX) gVirtualX->SetLineStyle(1); - if (gVirtualPS) gVirtualPS->SetLineStyle(1); + parent.GetPainter()->SetLineStyle(1); if (GetFillColor()) { - gPad->PaintFillArea(3,x2ar,y2ar); - gPad->PaintPolyLine(4,x2ar,y2ar); + parent.PaintFillArea(3,x2ar,y2ar); + parent.PaintPolyLine(4,x2ar,y2ar); } else { - gPad->PaintPolyLine(4,x2ar,y2ar); + parent.PaintPolyLine(4,x2ar,y2ar); } } else { - gPad->PaintPolyLine(3,x2ar,y2ar); + parent.PaintPolyLine(3,x2ar,y2ar); } } @@ -326,16 +318,15 @@ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, y1ar[i] = (1/ry)*(y1ar[i]-y1ndc)+ry1; } if (opt.Contains("<|")) { - if (gVirtualX) gVirtualX->SetLineStyle(1); - if (gVirtualPS) gVirtualPS->SetLineStyle(1); + parent.GetPainter()->SetLineStyle(1); if (GetFillColor()) { - gPad->PaintFillArea(3,x1ar,y1ar); - gPad->PaintPolyLine(4,x1ar,y1ar); + parent.PaintFillArea(3,x1ar,y1ar); + parent.PaintPolyLine(4,x1ar,y1ar); } else { - gPad->PaintPolyLine(4,x1ar,y1ar); + parent.PaintPolyLine(4,x1ar,y1ar); } } else { - gPad->PaintPolyLine(3,x1ar,y1ar); + parent.PaintPolyLine(3,x1ar,y1ar); } } } diff --git a/graf2d/graf/src/TBox.cxx b/graf2d/graf/src/TBox.cxx index ce4ea64d2efe3..06577f2eb63b6 100644 --- a/graf2d/graf/src/TBox.cxx +++ b/graf2d/graf/src/TBox.cxx @@ -16,7 +16,8 @@ #include "TBuffer.h" #include "TBox.h" #include "TVirtualPad.h" -#include "TVirtualX.h" +#include "TVirtualPadPainter.h" +#include "TCanvasImp.h" #include "TClass.h" #include "TMath.h" #include "TPoint.h" @@ -230,35 +231,65 @@ TBox *TBox::DrawBox(Double_t x1, Double_t y1,Double_t x2, Double_t y2) void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py) { + if (TestBit(kCannotMove)) return; + if (!gPad) return; - if (!gPad->IsEditable() && event != kMouseEnter) return; - if (TestBit(kCannotMove)) return; + auto &parent = *gPad; + + if (!parent.IsEditable() && event != kMouseEnter) return; Bool_t isBox = !(InheritsFrom("TPave") || InheritsFrom("TWbox")); - const Int_t kMaxDiff = 7; - const Int_t kMinSize = 20; + constexpr Int_t kMaxDiff = 7; + constexpr Int_t kMinSize = 20; - static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold; - static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp; + static Int_t px1, px2, py1, py2, dpx1, dpy2; + static Int_t px1p, px2p, py1p, py2p; static Double_t oldX1, oldY1, oldX2, oldY2; - static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE; - Int_t wx, wy; - TVirtualPad *parent = gPad; - Bool_t opaque = gPad->OpaqueMoving(); - Bool_t ropaque = gPad->OpaqueResizing(); + static Bool_t hasOld = kFALSE; + static enum { pNone, pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE } mode = pNone; + static bool firstPaint = kFALSE; + Bool_t opaque = parent.OpaqueMoving(); + Bool_t ropaque = parent.OpaqueResizing(); + + // convert to user coordinates and either paint ot set back + auto paint_or_set = [&parent,isBox,this](Bool_t paint) + { + auto x1 = parent.AbsPixeltoX(px1); + auto y1 = parent.AbsPixeltoY(py1); + auto x2 = parent.AbsPixeltoX(px2); + auto y2 = parent.AbsPixeltoY(py2); + if (!paint) { + if (isBox) { + if (parent.GetLogx()) { + x1 = TMath::Power(10, x1); + x2 = TMath::Power(10, x2); + } + if (parent.GetLogy()) { + y1 = TMath::Power(10, y1); + y2 = TMath::Power(10, y2); + } + } + SetX1(x1); + SetY1(y1); + SetX2(x2); + SetY2(y2); + } else if (firstPaint) { + firstPaint = kFALSE; + } else { + auto pp = parent.GetPainter(); + pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2}); + pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow); + } + }; HideToolTip(event); switch (event) { case kMouseEnter: - if (fTip) gPad->ResetToolTip(fTip); - break; - - case kButton1Double: - px1 = -1; //used by kButton1Up + if (fTip) parent.ResetToolTip(fTip); break; case kArrowKeyPress: @@ -268,360 +299,197 @@ void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py) oldY1 = fY1; oldX2 = fX2; oldY2 = fY2; - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); //Change line attributes only if necessary - if (GetFillColor()) - gVirtualX->SetLineColor(GetFillColor()); - else - gVirtualX->SetLineColor(1); - gVirtualX->SetLineWidth(2); + hasOld = kTRUE; // No break !!! case kMouseMotion: - px1 = gPad->XtoAbsPixel(GetX1()); - py1 = gPad->YtoAbsPixel(GetY1()); - px2 = gPad->XtoAbsPixel(GetX2()); - py2 = gPad->YtoAbsPixel(GetY2()); - - if (isBox) { - if (gPad->GetLogx()) { - if (fX1>0) px1 = gPad->XtoAbsPixel(TMath::Log10(fX1)); - if (fX2>0) px2 = gPad->XtoAbsPixel(TMath::Log10(fX2)); - } - if (gPad->GetLogy()) { - if (fY1>0) py1 = gPad->YtoAbsPixel(TMath::Log10(fY1)); - if (fY2>0) py2 = gPad->YtoAbsPixel(TMath::Log10(fY2)); - } - } - - if (px1 < px2) { - pxl = px1; - pxt = px2; - } else { - pxl = px2; - pxt = px1; - } - if (py1 < py2) { - pyl = py1; - pyt = py2; - } else { - pyl = py2; - pyt = py1; - } - - px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize(); - py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize(); - px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize(); - py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize(); - - if (px1p < px2p) { - pxlp = px1p; - pxtp = px2p; - } else { - pxlp = px2p; - pxtp = px1p; - } - if (py1p < py2p) { - pylp = py1p; - pytp = py2p; - } else { - pylp = py2p; - pytp = py1p; - } - - pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE; - - // case pA - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxl; pyold = pyl; pA = kTRUE; - gPad->SetCursor(kTopLeft); - } - // case pB - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) { - pxold = pxt; pyold = pyl; pB = kTRUE; - gPad->SetCursor(kTopRight); - } - // case pC - if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxt; pyold = pyt; pC = kTRUE; - gPad->SetCursor(kBottomRight); - } - // case pD - if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) { - pxold = pxl; pyold = pyt; pD = kTRUE; - gPad->SetCursor(kBottomLeft); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - TMath::Abs(py - pyl) < kMaxDiff) { // top edge - pxold = pxl; pyold = pyl; pTop = kTRUE; - gPad->SetCursor(kTopSide); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - TMath::Abs(py - pyt) < kMaxDiff) { // bottom edge - pxold = pxt; pyold = pyt; pBot = kTRUE; - gPad->SetCursor(kBottomSide); - } - - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && - TMath::Abs(px - pxl) < kMaxDiff) { // left edge - pxold = pxl; pyold = pyl; pL = kTRUE; - gPad->SetCursor(kLeftSide); - } - - if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) && - TMath::Abs(px - pxt) < kMaxDiff) { // right edge - pxold = pxt; pyold = pyt; pR = kTRUE; - gPad->SetCursor(kRightSide); - } - - if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) && - (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { // inside box - pxold = px; pyold = py; pINSIDE = kTRUE; + px1 = parent.XtoAbsPixel(isBox ? parent.XtoPad(GetX1()) : GetX1()); + py1 = parent.YtoAbsPixel(isBox ? parent.YtoPad(GetY1()) : GetY1()); + px2 = parent.XtoAbsPixel(isBox ? parent.XtoPad(GetX2()) : GetX2()); + py2 = parent.YtoAbsPixel(isBox ? parent.YtoPad(GetY2()) : GetY2()); + if (px1 > px2) + std::swap(px1, px2); + if (py1 < py2) + std::swap(py1, py2); + + px1p = parent.XtoAbsPixel(parent.GetX1()) + parent.GetBorderSize(); + py1p = parent.YtoAbsPixel(parent.GetY1()) - parent.GetBorderSize(); + px2p = parent.XtoAbsPixel(parent.GetX2()) - parent.GetBorderSize(); + py2p = parent.YtoAbsPixel(parent.GetY2()) + parent.GetBorderSize(); + if (px1p > px2p) + std::swap(px1p, px2p); + if (py1p < py2p) + std::swap(py1p, py2p); + + mode = pNone; + + if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pA; + parent.SetCursor(kTopLeft); + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py2) <= kMaxDiff) { + mode = pB; + parent.SetCursor(kTopRight); + } else if (TMath::Abs(px - px2) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pC; + parent.SetCursor(kBottomRight); + } else if (TMath::Abs(px - px1) <= kMaxDiff && TMath::Abs(py - py1) <= kMaxDiff) { + mode = pD; + parent.SetCursor(kBottomLeft); + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py2) < kMaxDiff) { + mode = pTop; + parent.SetCursor(kTopSide); + } else if ((px > px1 + kMaxDiff && px < px2 - kMaxDiff) && TMath::Abs(py - py1) < kMaxDiff) { + mode = pBot; + parent.SetCursor(kBottomSide); + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px1) < kMaxDiff) { + mode = pL; + parent.SetCursor(kLeftSide); + } else if ((py > py2 + kMaxDiff && py < py1 - kMaxDiff) && TMath::Abs(px - px2) < kMaxDiff) { + mode = pR; + parent.SetCursor(kRightSide); + } else if ((px > px1+kMaxDiff && px < px2-kMaxDiff) && (py > py2+kMaxDiff && py < py1-kMaxDiff)) { + dpx1 = px - px1; // cursor position relative to top-left corner + dpy2 = py - py2; + mode = pINSIDE; if (event == kButton1Down) - gPad->SetCursor(kMove); + parent.SetCursor(kMove); else - gPad->SetCursor(kCross); + parent.SetCursor(kCross); } - fResizing = kFALSE; - if (pA || pB || pC || pD || pTop || pL || pR || pBot) - fResizing = kTRUE; - - if (!pA && !pB && !pC && !pD && !pTop && !pL && !pR && !pBot && !pINSIDE) - gPad->SetCursor(kCross); + fResizing = (mode != pNone) && (mode != pINSIDE); + firstPaint = kTRUE; + if (mode == pNone) + parent.SetCursor(kCross); break; case kArrowKeyRelease: case kButton1Motion: - wx = wy = 0; - - if (pA) { - if (!ropaque) gVirtualX->DrawBox(pxold, pyt, pxt, pyold, TVirtualX::kHollow); // draw the old box - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (!ropaque) gVirtualX->DrawBox(px , pyt, pxt, py, TVirtualX::kHollow); // draw the new box - } - if (pB) { - if (!ropaque) gVirtualX->DrawBox(pxl , pyt, pxold, pyold, TVirtualX::kHollow); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py < pylp) { py = pylp; wy = py; } - if (!ropaque) gVirtualX->DrawBox(pxl , pyt, px , py, TVirtualX::kHollow); - } - if (pC) { - if (!ropaque) gVirtualX->DrawBox(pxl , pyl, pxold, pyold, TVirtualX::kHollow); - if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px > pxtp) { px = pxtp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (!ropaque) gVirtualX->DrawBox(pxl , pyl, px , py, TVirtualX::kHollow); - } - if (pD) { - if (!ropaque) gVirtualX->DrawBox(pxold, pyold, pxt, pyl, TVirtualX::kHollow); - if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; } - if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; } - if (px < pxlp) { px = pxlp; wx = px; } - if (py > pytp) { py = pytp; wy = py; } - if (!ropaque) gVirtualX->DrawBox(px , py , pxt, pyl, TVirtualX::kHollow); - } - if (pTop) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - py2 += py - pyold; - if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; } - if (py2 < py2p) { py2 = py2p; wy = py2; } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pBot) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - py1 += py - pyold; - if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; } - if (py1 > py1p) { py1 = py1p; wy = py1; } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pL) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - px1 += px - pxold; - if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; } - if (px1 < px1p) { px1 = px1p; wx = px1; } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pR) { - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - px2 += px - pxold; - if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; } - if (px2 > px2p) { px2 = px2p; wx = px2; } - if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); - } - if (pINSIDE) { - if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the old box - Int_t dx = px - pxold; - Int_t dy = py - pyold; - px1 += dx; py1 += dy; px2 += dx; py2 += dy; - if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; } - if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; } - if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; } - if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; } - if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the new box - } - - if (wx || wy) { - if (wx) px = wx; - if (wy) py = wy; - gVirtualX->Warp(px, py); + switch (mode) { + case pNone: + return; + case pA: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + paint_or_set(!ropaque); + break; + case pB: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + paint_or_set(!ropaque); + break; + case pC: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + paint_or_set(!ropaque); + break; + case pD: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + paint_or_set(!ropaque); + break; + case pTop: + if (!ropaque) paint_or_set(kTRUE); + py2 = TMath::Max(py2p, TMath::Min(py, py1 - kMinSize)); + paint_or_set(!ropaque); + break; + case pBot: + if (!ropaque) paint_or_set(kTRUE); + py1 = TMath::Min(py1p, TMath::Max(py, py2 + kMinSize)); + paint_or_set(!ropaque); + break; + case pL: + if (!ropaque) paint_or_set(kTRUE); + px1 = TMath::Max(px1p, TMath::Min(px, px2 - kMinSize)); + paint_or_set(!ropaque); + break; + case pR: + if (!ropaque) paint_or_set(kTRUE); + px2 = TMath::Min(px2p, TMath::Max(px, px1 + kMinSize)); + paint_or_set(!ropaque); + break; + case pINSIDE: + if (!opaque) paint_or_set(kTRUE); + px2 += px - dpx1 - px1; + px1 = px - dpx1; + py1 += py - dpy2 - py2; + py2 = py - dpy2; + if (px1 < px1p) { px2 += px1p - px1; px1 = px1p; } + if (px2 > px2p) { px1 -= px2 - px2p; px2 = px2p; } + if (py1 > py1p) { py2 -= py1 - py1p; py1 = py1p; } + if (py2 < py2p) { py1 += py2p - py2; py2 = py2p; } + paint_or_set(!opaque); + break; } - pxold = px; - pyold = py; - - - if ((pINSIDE && opaque) || (fResizing && ropaque)) { - if (pA) { - fX1 = gPad->AbsPixeltoX(pxold); - fY1 = gPad->AbsPixeltoY(pyt); - fX2 = gPad->AbsPixeltoX(pxt); - fY2 = gPad->AbsPixeltoY(pyold); - } - if (pB) { - fX1 = gPad->AbsPixeltoX(pxl); - fY1 = gPad->AbsPixeltoY(pyt); - fX2 = gPad->AbsPixeltoX(pxold); - fY2 = gPad->AbsPixeltoY(pyold); - } - if (pC) { - fX1 = gPad->AbsPixeltoX(pxl); - fY1 = gPad->AbsPixeltoY(pyold); - fX2 = gPad->AbsPixeltoX(pxold); - fY2 = gPad->AbsPixeltoY(pyl); - } - if (pD) { - fX1 = gPad->AbsPixeltoX(pxold); - fY1 = gPad->AbsPixeltoY(pyold); - fX2 = gPad->AbsPixeltoX(pxt); - fY2 = gPad->AbsPixeltoY(pyl); - } - if (pTop || pBot || pL || pR || pINSIDE) { - fX1 = gPad->AbsPixeltoX(px1); - fY1 = gPad->AbsPixeltoY(py1); - fX2 = gPad->AbsPixeltoX(px2); - fY2 = gPad->AbsPixeltoY(py2); + if ((mode == pINSIDE && opaque) || (fResizing && ropaque)) { + switch(mode) { + case pINSIDE: parent.ShowGuidelines(this, event, 'i', true); break; + case pTop: parent.ShowGuidelines(this, event, 't', true); break; + case pBot: parent.ShowGuidelines(this, event, 'b', true); break; + case pL: parent.ShowGuidelines(this, event, 'l', true); break; + case pR: parent.ShowGuidelines(this, event, 'r', true); break; + case pA: parent.ShowGuidelines(this, event, '1', true); break; + case pB: parent.ShowGuidelines(this, event, '2', true); break; + case pC: parent.ShowGuidelines(this, event, '3', true); break; + case pD: parent.ShowGuidelines(this, event, '4', true); break; + default: break; // not involved } - - if (isBox) { - if (gPad->GetLogx()) { - fX1 = TMath::Power(10,fX1); - fX2 = TMath::Power(10,fX2); - } - if (gPad->GetLogy()) { - fY1 = TMath::Power(10,fY1); - fY2 = TMath::Power(10,fY2); - } - } - - if (pINSIDE) gPad->ShowGuidelines(this, event, 'i', true); - if (pTop) gPad->ShowGuidelines(this, event, 't', true); - if (pBot) gPad->ShowGuidelines(this, event, 'b', true); - if (pL) gPad->ShowGuidelines(this, event, 'l', true); - if (pR) gPad->ShowGuidelines(this, event, 'r', true); - if (pA) gPad->ShowGuidelines(this, event, '1', true); - if (pB) gPad->ShowGuidelines(this, event, '2', true); - if (pC) gPad->ShowGuidelines(this, event, '3', true); - if (pD) gPad->ShowGuidelines(this, event, '4', true); - gPad->Modified(kTRUE); + parent.Modified(kTRUE); } break; case kButton1Up: + if (opaque || ropaque) + parent.ShowGuidelines(this, event); + if (gROOT->IsEscaped()) { gROOT->SetEscape(kFALSE); - if (opaque) { - this->SetX1(oldX1); - this->SetY1(oldY1); - this->SetX2(oldX2); - this->SetY2(oldY2); - gPad->Modified(kTRUE); - gPad->Update(); + if (opaque && (mode != pNone)) { + if (hasOld) { + SetX1(oldX1); + SetY1(oldY1); + SetX2(oldX2); + SetY2(oldY2); + } + hasOld = kFALSE; + mode = pNone; + fResizing = kFALSE; + parent.Modified(kTRUE); + parent.Update(); } break; } - if (opaque || ropaque) { - gPad->ShowGuidelines(this, event); - } else { - if (px1 < 0 ) break; - if (pA) { - fX1 = gPad->AbsPixeltoX(pxold); - fY1 = gPad->AbsPixeltoY(pyt); - fX2 = gPad->AbsPixeltoX(pxt); - fY2 = gPad->AbsPixeltoY(pyold); - } - if (pB) { - fX1 = gPad->AbsPixeltoX(pxl); - fY1 = gPad->AbsPixeltoY(pyt); - fX2 = gPad->AbsPixeltoX(pxold); - fY2 = gPad->AbsPixeltoY(pyold); - } - if (pC) { - fX1 = gPad->AbsPixeltoX(pxl); - fY1 = gPad->AbsPixeltoY(pyold); - fX2 = gPad->AbsPixeltoX(pxold); - fY2 = gPad->AbsPixeltoY(pyl); - } - if (pD) { - fX1 = gPad->AbsPixeltoX(pxold); - fY1 = gPad->AbsPixeltoY(pyold); - fX2 = gPad->AbsPixeltoX(pxt); - fY2 = gPad->AbsPixeltoY(pyl); - } - if (pTop || pBot || pL || pR || pINSIDE) { - fX1 = gPad->AbsPixeltoX(px1); - fY1 = gPad->AbsPixeltoY(py1); - fX2 = gPad->AbsPixeltoX(px2); - fY2 = gPad->AbsPixeltoY(py2); - } + if ((!opaque && mode == pINSIDE) || (!ropaque && fResizing)) + paint_or_set(kFALSE); - if (isBox) { - if (gPad->GetLogx()) { - fX1 = TMath::Power(10,fX1); - fX2 = TMath::Power(10,fX2); - } - if (gPad->GetLogy()) { - fY1 = TMath::Power(10,fY1); - fY2 = TMath::Power(10,fY2); - } - } - if (pINSIDE) { - // if it was not a pad that was moved then it must have been - // a box or something like that so we have to redraw the pad - if (parent == gPad) gPad->Modified(kTRUE); - } - } - - if (pA || pB || pC || pD || pTop || pL || pR || pBot) gPad->Modified(kTRUE); + if (mode != pNone) + parent.Modified(kTRUE); - if (!opaque) { - gVirtualX->SetLineColor(-1); - gVirtualX->SetLineWidth(-1); - } + mode = pNone; + fResizing = kFALSE; + hasOld = kFALSE; break; case kButton1Locate: + // Sergey: code is never used, has to be removed in ROOT7 ExecuteEvent(kButton1Down, px, py); while (true) { px = py = 0; - event = gVirtualX->RequestLocator(1, 1, px, py); + event = parent.GetCanvasImp()->RequestLocator(px, py); ExecuteEvent(kButton1Motion, px, py); diff --git a/graf2d/graf/src/TEllipse.cxx b/graf2d/graf/src/TEllipse.cxx index 588bde74b3c1c..2002b0f5b3025 100644 --- a/graf2d/graf/src/TEllipse.cxx +++ b/graf2d/graf/src/TEllipse.cxx @@ -479,6 +479,7 @@ void TEllipse::ExecuteEvent(Int_t event, Int_t px, Int_t py) if (gROOT->IsEscaped()) { gROOT->SetEscape(kFALSE); if (opaque) { + gPad->ShowGuidelines(this, event); this->SetX1(oldX1); this->SetY1(oldY1); this->SetR1(oldR1); diff --git a/graf2d/graf/src/TLatex.cxx b/graf2d/graf/src/TLatex.cxx index 5156438c6ae61..a7c9a691adb5c 100644 --- a/graf2d/graf/src/TLatex.cxx +++ b/graf2d/graf/src/TLatex.cxx @@ -15,8 +15,8 @@ #include "TMathText.h" #include "TMath.h" #include "TVirtualPad.h" +#include "TVirtualPadPainter.h" #include "TVirtualPS.h" -#include "TVirtualX.h" #include "snprintf.h" const Double_t kPI = TMath::Pi(); @@ -1357,13 +1357,13 @@ TLatex::TLatexFormSize TLatex::Analyse(Double_t x, Double_t y, const TextSpec_t result = fs1+fs2; } - else if (opSpec>-1) { + else if (opSpec > -1) { TextSpec_t newSpec = spec; newSpec.fFont = fItalic ? 152 : 122; char letter = '\243' + opSpec; if(opSpec == 75 || opSpec == 76) { newSpec.fFont = GetTextFont(); - if (gVirtualX->InheritsFrom("TGCocoa")) { + if (gPad->GetPainter()->IsCocoa()) { if (opSpec == 75) letter = '\201'; // AA Angstroem if (opSpec == 76) letter = '\214'; // aa Angstroem } else { @@ -1491,25 +1491,26 @@ TLatex::TLatexFormSize TLatex::Analyse(Double_t x, Double_t y, const TextSpec_t Double_t x2 = x+fs1.Width()/2, y2 = y -fs1.Over(); // tilde must be drawn separately on screen and on PostScript // because an adjustment is required along Y for PostScript. - TVirtualPS *saveps = gVirtualPS; - if (gVirtualPS) gVirtualPS = nullptr; - Double_t y22 = y2; - if (gVirtualX->InheritsFrom("TGCocoa")) y2 -= 4.7*sub; + Double_t xx, yy; - Rotate(gPad, spec.fAngle, x2, y2, xx, yy); - TText tilde; - tilde.SetTextFont(fTextFont); - tilde.SetTextColor(spec.fColor); - tilde.SetTextSize(0.9*spec.fSize); - tilde.SetTextAlign(22); - tilde.SetTextAngle(fTextAngle); - tilde.PaintText(xx,yy,"~"); - if (saveps) { - gVirtualPS = saveps; - if (!strstr(gVirtualPS->GetTitle(),"IMG")) y22 -= 4*sub; - Rotate(gPad, spec.fAngle, x2, y22, xx, yy); - gVirtualPS->SetTextAlign(22); - gVirtualPS->Text(xx, yy, "~"); + if (auto ps = gPad->GetPainter()->GetPS()) { + if (!strstr(ps->GetTitle(), "IMG")) + y2 -= 4*sub; + Rotate(gPad, spec.fAngle, x2, y2, xx, yy); + ps->SetTextAlign(22); + ps->Text(xx, yy, "~"); + } else { + if (gPad->GetPainter()->IsCocoa()) + y2 -= 4.7*sub; + Rotate(gPad, spec.fAngle, x2, y2, xx, yy); + // TODO: use pad painter SetAttText and DrawText directly + TText tilde; + tilde.SetTextFont(fTextFont); + tilde.SetTextColor(spec.fColor); + tilde.SetTextSize(0.9*spec.fSize); + tilde.SetTextAlign(22); + tilde.SetTextAngle(fTextAngle); + tilde.PaintText(xx,yy,"~"); } break; } @@ -2150,88 +2151,76 @@ void TLatex::PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, c TAttText::Modify(); // Change text attributes only if necessary. - TVirtualPS *saveps = gVirtualPS; - - if (gVirtualPS) { - if (gVirtualPS->InheritsFrom("TTeXDump")) { - gVirtualPS->SetTextAngle(angle); - TString t(text1); - if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) { - t.ReplaceAll("#LT","\\langle"); - t.ReplaceAll("#GT","\\rangle"); - t.ReplaceAll("#club","\\clubsuit"); - t.ReplaceAll("#spade","\\spadesuit"); - t.ReplaceAll("#heart","\\heartsuit"); - t.ReplaceAll("#diamond","\\diamondsuit"); - t.ReplaceAll("#voidn","\\wp"); - t.ReplaceAll("#voidb","f"); - t.ReplaceAll("#ocopyright","\\copyright"); - t.ReplaceAll("#trademark","TM"); - t.ReplaceAll("#void3","TM"); - t.ReplaceAll("#oright","R"); - t.ReplaceAll("#void1","R"); - t.ReplaceAll("#3dots","\\ldots"); - t.ReplaceAll("#lbar","\\mid"); - t.ReplaceAll("#bar","\\wwbar"); - t.ReplaceAll("#void8","\\mid"); - t.ReplaceAll("#divide","\\div"); - t.ReplaceAll("#Jgothic","\\Im"); - t.ReplaceAll("#Rgothic","\\Re"); - t.ReplaceAll("#doublequote","\""); - t.ReplaceAll("#plus","+"); - t.ReplaceAll("#minus","-"); - t.ReplaceAll("#/","/"); - t.ReplaceAll("#upoint","."); - t.ReplaceAll("#aa","\\mbox{\\aa}"); - t.ReplaceAll("#AA","\\mbox{\\AA}"); - - t.ReplaceAll("#omicron","o"); - t.ReplaceAll("#Alpha","A"); - t.ReplaceAll("#Beta","B"); - t.ReplaceAll("#Epsilon","E"); - t.ReplaceAll("#Zeta","Z"); - t.ReplaceAll("#Eta","H"); - t.ReplaceAll("#Iota","I"); - t.ReplaceAll("#Kappa","K"); - t.ReplaceAll("#Mu","M"); - t.ReplaceAll("#Nu","N"); - t.ReplaceAll("#Omicron","O"); - t.ReplaceAll("#Rho","P"); - t.ReplaceAll("#Tau","T"); - t.ReplaceAll("#Chi","X"); - t.ReplaceAll("#varomega","\\varpi"); - - t.ReplaceAll("#varUpsilon","?"); - t.ReplaceAll("#corner","?"); - t.ReplaceAll("#ltbar","?"); - t.ReplaceAll("#bottombar","?"); - t.ReplaceAll("#notsubset","?"); - t.ReplaceAll("#arcbottom","?"); - t.ReplaceAll("#cbar","?"); - t.ReplaceAll("#arctop","?"); - t.ReplaceAll("#topbar","?"); - t.ReplaceAll("#arcbar","?"); - t.ReplaceAll("#downleftarrow","?"); - t.ReplaceAll("#splitline","\\genfrac{}{}{0pt}{}"); - - t.ReplaceAll("#","\\"); - t.ReplaceAll("%","\\%"); - } - gVirtualPS->Text(x,y,t.Data()); - } else { - Bool_t saveb = gPad->IsBatch(); - gPad->SetBatch(kTRUE); - if (!PaintLatex1( x, y, angle, size, text1)) { - if (saveps) gVirtualPS = saveps; - return; - } - gPad->SetBatch(saveb); - } - gVirtualPS = nullptr; + auto ps = gPad->GetPainter()->GetPS(); + + if (ps && ps->InheritsFrom("TTeXDump")) { + TString t(text1); + if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) { + t.ReplaceAll("#LT","\\langle"); + t.ReplaceAll("#GT","\\rangle"); + t.ReplaceAll("#club","\\clubsuit"); + t.ReplaceAll("#spade","\\spadesuit"); + t.ReplaceAll("#heart","\\heartsuit"); + t.ReplaceAll("#diamond","\\diamondsuit"); + t.ReplaceAll("#voidn","\\wp"); + t.ReplaceAll("#voidb","f"); + t.ReplaceAll("#ocopyright","\\copyright"); + t.ReplaceAll("#trademark","TM"); + t.ReplaceAll("#void3","TM"); + t.ReplaceAll("#oright","R"); + t.ReplaceAll("#void1","R"); + t.ReplaceAll("#3dots","\\ldots"); + t.ReplaceAll("#lbar","\\mid"); + t.ReplaceAll("#bar","\\wwbar"); + t.ReplaceAll("#void8","\\mid"); + t.ReplaceAll("#divide","\\div"); + t.ReplaceAll("#Jgothic","\\Im"); + t.ReplaceAll("#Rgothic","\\Re"); + t.ReplaceAll("#doublequote","\""); + t.ReplaceAll("#plus","+"); + t.ReplaceAll("#minus","-"); + t.ReplaceAll("#/","/"); + t.ReplaceAll("#upoint","."); + t.ReplaceAll("#aa","\\mbox{\\aa}"); + t.ReplaceAll("#AA","\\mbox{\\AA}"); + + t.ReplaceAll("#omicron","o"); + t.ReplaceAll("#Alpha","A"); + t.ReplaceAll("#Beta","B"); + t.ReplaceAll("#Epsilon","E"); + t.ReplaceAll("#Zeta","Z"); + t.ReplaceAll("#Eta","H"); + t.ReplaceAll("#Iota","I"); + t.ReplaceAll("#Kappa","K"); + t.ReplaceAll("#Mu","M"); + t.ReplaceAll("#Nu","N"); + t.ReplaceAll("#Omicron","O"); + t.ReplaceAll("#Rho","P"); + t.ReplaceAll("#Tau","T"); + t.ReplaceAll("#Chi","X"); + t.ReplaceAll("#varomega","\\varpi"); + + t.ReplaceAll("#varUpsilon","?"); + t.ReplaceAll("#corner","?"); + t.ReplaceAll("#ltbar","?"); + t.ReplaceAll("#bottombar","?"); + t.ReplaceAll("#notsubset","?"); + t.ReplaceAll("#arcbottom","?"); + t.ReplaceAll("#cbar","?"); + t.ReplaceAll("#arctop","?"); + t.ReplaceAll("#topbar","?"); + t.ReplaceAll("#arcbar","?"); + t.ReplaceAll("#downleftarrow","?"); + t.ReplaceAll("#splitline","\\genfrac{}{}{0pt}{}"); + + t.ReplaceAll("#","\\"); + t.ReplaceAll("%","\\%"); + } + ps->SetTextAngle(angle); + ps->Text(x, y, t.Data()); + } else { + PaintLatex1(x, y, angle, size, text1); } - - if (!gPad->IsBatch()) PaintLatex1( x, y, angle, size, text1); - if (saveps) gVirtualPS = saveps; } //////////////////////////////////////////////////////////////////////////////// @@ -2255,30 +2244,23 @@ Int_t TLatex::PaintLatex1(Double_t x, Double_t y, Double_t angle, Double_t size, // Do not use Latex if font is low precision. if (fTextFont % 10 < 2) { - if (gVirtualX) gVirtualX->SetTextAngle(angle); - if (gVirtualPS) gVirtualPS->SetTextAngle(angle); - gPad->PaintText(x,y,text1); + gPad->GetPainter()->SetTextAngle(angle); + gPad->PaintText(x, y, text1); return 1; } - Bool_t saveb = gPad->IsBatch(); // Paint the text using TMathText if contains a "\" if (strstr(text1,"\\")) { - TMathText tm; - tm.SetTextAlign(GetTextAlign()); - tm.SetTextFont(GetTextFont()); - tm.SetTextColor(GetTextColor()); - tm.PaintMathText(x, y, angle, size, text1); - // If PDF, paint using TLatex - if (gVirtualPS) { - if (gVirtualPS->InheritsFrom("TPDF") || - gVirtualPS->InheritsFrom("TSVG")) { - newText.ReplaceAll("\\","#"); - gPad->SetBatch(kTRUE); - } else { - return 1; - } + auto ps = gPad->GetPainter()->GetPS(); + // If PDF or SVG, paint using TLatex + if (ps && (ps->InheritsFrom("TPDF") || ps->InheritsFrom("TSVG"))) { + newText.ReplaceAll("\\","#"); } else { + TMathText tm; + tm.SetTextAlign(GetTextAlign()); + tm.SetTextFont(GetTextFont()); + tm.SetTextColor(GetTextColor()); + tm.PaintMathText(x, y, angle, size, text1); return 1; } } @@ -2334,7 +2316,6 @@ Int_t TLatex::PaintLatex1(Double_t x, Double_t y, Double_t angle, Double_t size, Analyse(x,y,newSpec,text,length); } - gPad->SetBatch(saveb); SetTextSize(saveSize); SetTextAngle(angle); SetTextFont(saveFont); diff --git a/graf2d/graf/src/TLine.cxx b/graf2d/graf/src/TLine.cxx index b7993912af2cc..8c1e791b25ede 100644 --- a/graf2d/graf/src/TLine.cxx +++ b/graf2d/graf/src/TLine.cxx @@ -17,7 +17,8 @@ #include "TLine.h" #include "TVirtualPad.h" #include "TClass.h" -#include "TVirtualX.h" +#include "TVirtualPadPainter.h" +#include "TCanvasImp.h" #include "TMath.h" #include "TPoint.h" @@ -130,19 +131,72 @@ TLine *TLine::DrawLineNDC(Double_t x1, Double_t y1, Double_t x2, Double_t y2) void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - if (!gPad) return; + if (!gPad || !gPad->IsEditable()) return; - Int_t kMaxDiff = 20; - static Int_t d1,d2,px1,px2,py1,py2; - static Int_t pxold, pyold, px1old, py1old, px2old, py2old; + constexpr Int_t kMaxDiff = 20; + static Int_t px1,px2,py1,py2,pxold,pyold; static Double_t oldX1, oldY1, oldX2, oldY2; - static Bool_t p1, p2, pL, ndcsav; - Double_t dpx,dpy,xp1,yp1; - Int_t dx, dy; + static Int_t selectPoint; + + auto parent = gPad; + + Bool_t opaque = parent->OpaqueMoving(); + + auto action = [this, parent](Int_t code, Int_t _x1, Int_t _y1, Int_t _x2 = 0, Int_t _y2 = 0) { + Double_t x1, y1, x2, y2; + + Bool_t isndc = TestBit(kLineNDC); - Bool_t opaque = gPad->OpaqueMoving(); + if (isndc) { + x1 = (1. * _x1 / parent->GetWw() - parent->GetAbsXlowNDC()) / parent->GetAbsWNDC(); + y1 = ((1 - 1. * _y1 / parent->GetWh()) - parent->GetAbsYlowNDC()) / parent->GetAbsHNDC(); + x2 = (1. * _x2 / parent->GetWw() - parent->GetAbsXlowNDC()) / parent->GetAbsWNDC(); + y2 = ((1 - 1. * _y2 / parent->GetWh()) - parent->GetAbsYlowNDC()) / parent->GetAbsHNDC(); + } else { + x1 = parent->AbsPixeltoX(_x1); + y1 = parent->AbsPixeltoY(_y1); + x2 = parent->AbsPixeltoX(_x2); + y2 = parent->AbsPixeltoY(_y2); + } + if (code == 0) { + auto pp = parent->GetPainter(); + pp->SetAttLine(*this); + if (isndc) + pp->DrawLineNDC(x1, y1, x2, y2); + else + pp->DrawLine(x1, y1, x2, y2); + } else { + if (!isndc && parent->GetLogx()) { + x1 = TMath::Power(10, x1); + x2 = TMath::Power(10, x2); + } + if (!isndc && parent->GetLogy()) { + y1 = TMath::Power(10, y1); + y2 = TMath::Power(10, y2); + } - if (!gPad->IsEditable()) return; + if (code & 1) { + SetX1(x1); + SetY1(y1); + } + if (code & 2) { + SetX2(x2); + SetY2(y2); + } + if (TestBit(kVertical)) { + if (code & 1) + SetX2(GetX1()); + else + SetX1(GetX2()); + } + if (TestBit(kHorizontal)) { + if (code & 1) + SetY2(GetY1()); + else + SetY1(GetY2()); + } + } + }; switch (event) { @@ -152,134 +206,76 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) oldY1 = GetY1(); oldX2 = GetX2(); oldY2 = GetY2(); - ndcsav = TestBit(kLineNDC); - if (!opaque) { - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); //Change line attributes only if necessary - } // No break !!! case kMouseMotion: if (TestBit(kLineNDC)) { - px1 = gPad->UtoPixel(GetX1()); - py1 = gPad->VtoPixel(GetY1()); - px2 = gPad->UtoPixel(GetX2()); - py2 = gPad->VtoPixel(GetY2()); + px1 = parent->UtoAbsPixel(GetX1()); + py1 = parent->VtoAbsPixel(GetY1()); + px2 = parent->UtoAbsPixel(GetX2()); + py2 = parent->VtoAbsPixel(GetY2()); } else { - px1 = gPad->XtoAbsPixel(gPad->XtoPad(GetX1())); - py1 = gPad->YtoAbsPixel(gPad->YtoPad(GetY1())); - px2 = gPad->XtoAbsPixel(gPad->XtoPad(GetX2())); - py2 = gPad->YtoAbsPixel(gPad->YtoPad(GetY2())); + px1 = parent->XtoAbsPixel(parent->XtoPad(GetX1())); + py1 = parent->YtoAbsPixel(parent->YtoPad(GetY1())); + px2 = parent->XtoAbsPixel(parent->XtoPad(GetX2())); + py2 = parent->YtoAbsPixel(parent->YtoPad(GetY2())); } - p1 = p2 = pL = kFALSE; - d1 = abs(px1 - px) + abs(py1-py); //simply take sum of pixels differences - if (d1 < kMaxDiff) { //*-*================>OK take point number 1 - px1old = px1; py1old = py1; - p1 = kTRUE; - gPad->SetCursor(kPointer); - return; - } - d2 = abs(px2 - px) + abs(py2-py); //simply take sum of pixels differences - if (d2 < kMaxDiff) { //*-*================>OK take point number 2 - px2old = px2; py2old = py2; - p2 = kTRUE; - gPad->SetCursor(kPointer); - return; + //simply take sum of pixels differences + if (abs(px1 - px) + abs(py1 - py) < kMaxDiff) { //*-*================>OK take point number 1 + selectPoint = 1; + parent->SetCursor(kPointer); + } else if (abs(px2 - px) + abs(py2 - py) < kMaxDiff) { //*-*================>OK take point number 2 + selectPoint = 2; + parent->SetCursor(kPointer); + } else { + selectPoint = 3; + pxold = px; + pyold = py; + parent->SetCursor(kMove); } - pL = kTRUE; - pxold = px; pyold = py; - gPad->SetCursor(kMove); - break; case kArrowKeyRelease: case kButton1Motion: - - if (p1) { - if (!opaque) { - gVirtualX->DrawLine(px1old, py1old, px2, py2); - gVirtualX->DrawLine(px, py, px2, py2); - } else { - if (ndcsav) { - SetNDC(kFALSE); - SetX2(gPad->GetX1() + oldX2*(gPad->GetX2()-gPad->GetX1())); - SetY2(gPad->GetY1() + oldY2*(gPad->GetY2()-gPad->GetY1())); - } - SetX1(gPad->AbsPixeltoX(px)); - SetY1(gPad->AbsPixeltoY(py)); - } - px1old = px; - py1old = py; - } - if (p2) { - if (!opaque) { - gVirtualX->DrawLine(px1, py1, px2old, py2old); - gVirtualX->DrawLine(px1, py1, px, py); - } else { - if (ndcsav) { - SetNDC(kFALSE); - SetX1(gPad->GetX1() + oldX1*(gPad->GetX2()-gPad->GetX1())); - SetY1(gPad->GetY1() + oldY1*(gPad->GetY2()-gPad->GetY1())); - } - SetX2(gPad->AbsPixeltoX(px)); - SetY2(gPad->AbsPixeltoY(py)); - } - px2old = px; - py2old = py; - } - if (pL) { - if (!opaque) gVirtualX->DrawLine(px1, py1, px2, py2); - dx = px-pxold; dy = py-pyold; - px1 += dx; py1 += dy; px2 += dx; py2 += dy; - if (!opaque) gVirtualX->DrawLine(px1, py1, px2, py2); + if (!opaque) + action(0, px1, py1, px2, py2); + if (selectPoint == 1) { + px1 = px; + py1 = py; + } else if (selectPoint == 2) { + px2 = px; + py2 = py; + } else if (selectPoint == 3) { + px1 += px - pxold; + py1 += py - pyold; + px2 += px - pxold; + py2 += py -pyold; pxold = px; pyold = py; - if (opaque) { - if (ndcsav) SetNDC(kFALSE); - SetX1(gPad->AbsPixeltoX(px1)); - SetY1(gPad->AbsPixeltoY(py1)); - SetX2(gPad->AbsPixeltoX(px2)); - SetY2(gPad->AbsPixeltoY(py2)); - } } + action(!opaque ? 0 : selectPoint, px1, py1, px2, py2); if (opaque) { - if (p1) { + if (selectPoint == 1) { //check in which corner the BBox is edited - if (GetX1() > GetX2()) { - if (GetY1() > GetY2()) - gPad->ShowGuidelines(this, event, '2', true); - else - gPad->ShowGuidelines(this, event, '3', true); - } else { - if (GetY1() > GetY2()) - gPad->ShowGuidelines(this, event, '1', true); - else - gPad->ShowGuidelines(this, event, '4', true); - } - } - if (p2) { + if (GetX1() > GetX2()) + parent->ShowGuidelines(this, event, GetY1() > GetY2() ? '2' : '3', true); + else + parent->ShowGuidelines(this, event, GetY1() > GetY2() ? '1' : '4', true); + } else if (selectPoint == 2) { //check in which corner the BBox is edited - if (GetX1() > GetX2()) { - if (GetY1() > GetY2()) - gPad->ShowGuidelines(this, event, '4', true); - else - gPad->ShowGuidelines(this, event, '1', true); - } else { - if (GetY1() > GetY2()) - gPad->ShowGuidelines(this, event, '3', true); - else - gPad->ShowGuidelines(this, event, '2', true); - } + if (GetX1() > GetX2()) + parent->ShowGuidelines(this, event, GetY1() > GetY2() ? '4' : '1', true); + else + parent->ShowGuidelines(this, event, GetY1() > GetY2() ? '3' : '2', true); + } else if (selectPoint == 3) { + parent->ShowGuidelines(this, event, 'i', true); } - if (pL) { - gPad->ShowGuidelines(this, event, 'i', true); - } - gPad->Modified(kTRUE); - gPad->Update(); + parent->Modified(kTRUE); + parent->Update(); } break; @@ -292,76 +288,29 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) SetY1(oldY1); SetX2(oldX2); SetY2(oldY2); - gPad->Modified(kTRUE); - gPad->Update(); + parent->ShowGuidelines(this, event); + parent->Modified(kTRUE); + parent->Update(); } break; } if (opaque) { - if (ndcsav && !TestBit(kLineNDC)) { - SetX1((GetX1() - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())); - SetX2((GetX2() - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())); - SetY1((GetY1() - gPad->GetY1())/(gPad->GetY2()-gPad->GetY1())); - SetY2((GetY2() - gPad->GetY1())/(gPad->GetY2()-gPad->GetY1())); - SetNDC(); - } - gPad->ShowGuidelines(this, event); + parent->ShowGuidelines(this, event); } else { - if (TestBit(kLineNDC)) { - dpx = gPad->GetX2() - gPad->GetX1(); - dpy = gPad->GetY2() - gPad->GetY1(); - xp1 = gPad->GetX1(); - yp1 = gPad->GetY1(); - if (p1) { - SetX1((gPad->AbsPixeltoX(px)-xp1)/dpx); - SetY1((gPad->AbsPixeltoY(py)-yp1)/dpy); - } - if (p2) { - SetX2((gPad->AbsPixeltoX(px)-xp1)/dpx); - SetY2((gPad->AbsPixeltoY(py)-yp1)/dpy); - } - if (pL) { - SetX1((gPad->AbsPixeltoX(px1)-xp1)/dpx); - SetY1((gPad->AbsPixeltoY(py1)-yp1)/dpy); - SetX2((gPad->AbsPixeltoX(px2)-xp1)/dpx); - SetY2((gPad->AbsPixeltoY(py2)-yp1)/dpy); - } - } else { - if (p1) { - SetX1(gPad->PadtoX(gPad->AbsPixeltoX(px))); - SetY1(gPad->PadtoY(gPad->AbsPixeltoY(py))); - } - if (p2) { - SetX2(gPad->PadtoX(gPad->AbsPixeltoX(px))); - SetY2(gPad->PadtoY(gPad->AbsPixeltoY(py))); - } - if (pL) { - SetX1(gPad->PadtoX(gPad->AbsPixeltoX(px1))); - SetY1(gPad->PadtoY(gPad->AbsPixeltoY(py1))); - SetX2(gPad->PadtoX(gPad->AbsPixeltoX(px2))); - SetY2(gPad->PadtoY(gPad->AbsPixeltoY(py2))); - } - } - if (TestBit(kVertical)) { - if (p1) SetX2(GetX1()); - if (p2) SetX1(GetX2()); - } - if (TestBit(kHorizontal)) { - if (p1) SetY2(GetY1()); - if (p2) SetY1(GetY2()); - } - gPad->Modified(kTRUE); - gPad->Update(); - if (!opaque) gVirtualX->SetLineColor(-1); + action(selectPoint, px1, py1, px2, py2); + parent->Modified(kTRUE); + parent->Update(); } + selectPoint = 0; break; case kButton1Locate: + // Sergey: code is never used, has to be removed in ROOT7 ExecuteEvent(kButton1Down, px, py); while (true) { px = py = 0; - event = gVirtualX->RequestLocator(1,1,px,py); + event = parent->GetCanvasImp()->RequestLocator(px, py); ExecuteEvent(kButton1Motion, px, py); diff --git a/graf2d/graf/src/TMathText.cxx b/graf2d/graf/src/TMathText.cxx index e907f7eb511ff..db37252c02cbc 100644 --- a/graf2d/graf/src/TMathText.cxx +++ b/graf2d/graf/src/TMathText.cxx @@ -18,8 +18,8 @@ #include "TMathText.h" #include "TMath.h" #include "TVirtualPad.h" +#include "TVirtualPadPainter.h" #include "TVirtualPS.h" -#include "TVirtualX.h" #include "TText.h" #include "../../../graf2d/mathtext/inc/mathtext.h" @@ -583,20 +583,13 @@ void TMathText::PaintMathText(Double_t x, Double_t y, Double_t angle, Short_t saveAlign = fTextAlign; TAttText::Modify(); - if (gVirtualPS) { // Initialise TMathTextRenderer - if (gPad->IsBatch()) { - if (gVirtualPS->InheritsFrom("TImageDump")) gPad->PaintText(0, 0, ""); - } + if (auto ps = gPad->GetPainter()->GetPS()) { // Initialise TMathTextRenderer + if (ps->InheritsFrom("TImageDump")) gPad->PaintText(0, 0, ""); } // Do not use Latex if font is low precision. if (fTextFont % 10 < 2) { - if (gVirtualX) { - gVirtualX->SetTextAngle(angle); - } - if (gVirtualPS) { - gVirtualPS->SetTextAngle(angle); - } + gPad->GetPainter()->SetTextAngle(angle); gPad->PaintText(x, y, text1); return; } diff --git a/graf2d/graf/src/TWbox.cxx b/graf2d/graf/src/TWbox.cxx index a4be334f69f5f..a2fb8b9bd8619 100644 --- a/graf2d/graf/src/TWbox.cxx +++ b/graf2d/graf/src/TWbox.cxx @@ -14,9 +14,9 @@ #include "Strlen.h" #include "TWbox.h" #include "TColor.h" +#include "TStyle.h" #include "TVirtualPad.h" -#include "TVirtualX.h" -#include "TPoint.h" +#include "TVirtualPadPainter.h" /** \class TWbox @@ -135,69 +135,115 @@ void TWbox::PaintWbox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, void TWbox::PaintFrame(Double_t x1, Double_t y1,Double_t x2, Double_t y2, Color_t color, Short_t bordersize, Short_t bordermode, - Bool_t tops) + Bool_t /* tops */) { - if (!gPad) return; - if (bordermode == 0) return; - if (bordersize <= 0) bordersize = 2; + if (bordermode == 0) + return; - Short_t pxl,pyl,pxt,pyt,px1,py1,px2,py2; - Double_t xl, xt, yl, yt; + auto oldcolor = GetFillColor(); + SetFillColor(color); - // Compute real left bottom & top right of the box in pixels - px1 = gPad->XtoPixel(x1); py1 = gPad->YtoPixel(y1); - px2 = gPad->XtoPixel(x2); py2 = gPad->YtoPixel(y2); - if (px1 < px2) {pxl = px1; pxt = px2; xl = x1; xt = x2; } - else {pxl = px2; pxt = px1; xl = x2; xt = x1;} - if (py1 > py2) {pyl = py1; pyt = py2; yl = y1; yt = y2;} - else {pyl = py2; pyt = py1; yl = y2; yt = y1;} - - if (!gPad->IsBatch()) { - TPoint frame[7]; - - // GetDarkColor() and GetLightColor() use GetFillColor() - Color_t oldcolor = GetFillColor(); - SetFillColor(color); - TAttFill::Modify(); - - // Draw top&left part of the box - frame[0].fX = pxl; frame[0].fY = pyl; - frame[1].fX = pxl + bordersize; frame[1].fY = pyl - bordersize; - frame[2].fX = frame[1].fX; frame[2].fY = pyt + bordersize; - frame[3].fX = pxt - bordersize; frame[3].fY = frame[2].fY; - frame[4].fX = pxt; frame[4].fY = pyt; - frame[5].fX = pxl; frame[5].fY = pyt; - frame[6].fX = pxl; frame[6].fY = pyl; - - if (bordermode == -1) gVirtualX->SetFillColor(GetDarkColor()); - else gVirtualX->SetFillColor(GetLightColor()); - gVirtualX->DrawFillArea(7, frame); - - // Draw bottom&right part of the box - frame[0].fX = pxl; frame[0].fY = pyl; - frame[1].fX = pxl + bordersize; frame[1].fY = pyl - bordersize; - frame[2].fX = pxt - bordersize; frame[2].fY = frame[1].fY; - frame[3].fX = frame[2].fX; frame[3].fY = pyt + bordersize; - frame[4].fX = pxt; frame[4].fY = pyt; - frame[5].fX = pxt; frame[5].fY = pyl; - frame[6].fX = pxl; frame[6].fY = pyl; - - if (bordermode == -1) gVirtualX->SetFillColor(TColor::GetColorBright(GetFillColor())); - else gVirtualX->SetFillColor(TColor::GetColorDark(GetFillColor())); - gVirtualX->DrawFillArea(7, frame); - - gVirtualX->SetFillColor(-1); - SetFillColor(oldcolor); + PaintBorderOn(gPad, x1, y1, x2, y2, bordersize, bordermode); + + SetFillColor(oldcolor); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Paint a 3D border around a box. +/// Used also by the pad painter + +void TWbox::PaintBorderOn(TVirtualPad *pad, + Double_t x1, Double_t y1,Double_t x2 ,Double_t y2, + Short_t bordersize, Short_t bordermode, Bool_t with_selection) +{ + if (bordermode == 0) + return; + if (bordersize <= 0) + bordersize = 2; + + auto pp = pad->GetPainter(); + if (!pp) + return; + + Double_t ww = pad->GetWw(), wh = pad->GetWh(); + + if (pp->GetPS()) { + // SL: need to calculate page size to get real coordiantes for border + // TODO: Code can be removed if border not need to be exact pixel size + Float_t xsize = 20, ysize = 26; + gStyle->GetPaperSize(xsize, ysize); + Double_t ratio = wh/ww; + if (xsize * ratio > ysize) + xsize = ysize/ratio; + else + ysize = xsize*ratio; + ww = 72 / 2.54 * xsize; + wh = 72 / 2.54 * ysize; } - if (!tops) return; + const Double_t realBsX = bordersize / (pad->GetAbsWNDC() * ww) * (pad->GetX2() - pad->GetX1()); + const Double_t realBsY = bordersize / (pad->GetAbsHNDC() * wh) * (pad->GetY2() - pad->GetY1()); + + // GetColorDark() and GetColorBright() use GetFillColor() + Color_t fillcolor = GetFillColor(); + Color_t light = !fillcolor ? 0 : GetLightColor(); + Color_t dark = !fillcolor ? 0 : GetDarkColor(); + + Double_t xl, xt, yl, yt; - // same for PostScript - // Double_t dx = (xt - xl) *Double_t(bordersize)/Double_t(pxt - pxl); - // Int_t border = gVirtualPS->XtoPS(xt) - gVirtualPS->XtoPS(xt-dx); + // Compute real left bottom & top right of the box in pixels + if (pad->XtoPixel(x1) < pad->XtoPixel(x2)) { + xl = x1; + xt = x2; + } else { + xl = x2; + xt = x1; + } + if (pad->YtoPixel(y1) > pad->YtoPixel(y2)) { + yl = y1; + yt = y2; + } else { + yl = y2; + yt = y1; + } - gPad->PaintBorderPS(xl, yl, xt, yt, bordermode, bordersize, - GetDarkColor(), GetLightColor()); + Double_t frameXs[7] = {}, frameYs[7] = {}; + + // Draw top&left part of the box + frameXs[0] = xl; frameYs[0] = yl; + frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY; + frameXs[2] = frameXs[1]; frameYs[2] = yt - realBsY; + frameXs[3] = xt - realBsX; frameYs[3] = frameYs[2]; + frameXs[4] = xt; frameYs[4] = yt; + frameXs[5] = xl; frameYs[5] = yt; + frameXs[6] = xl; frameYs[6] = yl; + + SetFillColor(bordermode == -1 ? dark : light); + pp->SetAttFill(*this); + pp->DrawFillArea(7, frameXs, frameYs); + + // Draw bottom&right part of the box + frameXs[0] = xl; frameYs[0] = yl; + frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY; + frameXs[2] = xt - realBsX; frameYs[2] = frameYs[1]; + frameXs[3] = frameXs[2]; frameYs[3] = yt - realBsY; + frameXs[4] = xt; frameYs[4] = yt; + frameXs[5] = xt; frameYs[5] = yl; + frameXs[6] = xl; frameYs[6] = yl; + + SetFillColor(bordermode == -1 ? light : dark); + pp->SetAttFill(*this); + pp->DrawFillArea(7, frameXs, frameYs); + + SetFillColor(fillcolor); + + if (with_selection) { + Color_t oldlinecolor = GetLineColor(); + SetLineColor(GetFillColor() != 2 ? 2 : 4); + pp->SetAttLine(*this); + pp->DrawBox(xl + realBsX, yl + realBsY, xt - realBsX, yt - realBsY, TVirtualPadPainter::kHollow); + SetLineColor(oldlinecolor); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/postscript/inc/TPostScript.h b/graf2d/postscript/inc/TPostScript.h index acf9837a96fac..c95313db5daa2 100644 --- a/graf2d/postscript/inc/TPostScript.h +++ b/graf2d/postscript/inc/TPostScript.h @@ -48,6 +48,8 @@ class TPostScript : public TVirtualPS { Float_t fRed; ///< Per cent of red Float_t fGreen; ///< Per cent of green Float_t fBlue; ///< Per cent of blue + Float_t fWidth; ///< Current line width + Int_t fStyle; ///< Current line style Float_t fLineScale; ///< Line width scale factor Int_t fSave; ///< Number of gsave for restore Int_t fNXzone; ///< Number of zones along X @@ -55,7 +57,6 @@ class TPostScript : public TVirtualPS { Int_t fIXzone; ///< Current zone along X Int_t fIYzone; ///< Current zone along Y Float_t fMarkerSizeCur; ///< current transformed value of marker size - Int_t fCurrentColor; ///< current Postscript color index Int_t fNpages; ///< number of pages Int_t fType; ///< PostScript workstation type Int_t fMode; ///< PostScript mode @@ -92,12 +93,12 @@ class TPostScript : public TVirtualPS { void Close(Option_t *opt="") override; Int_t CMtoPS(Double_t u) {return Int_t(0.5 + 72*u/2.54);} void DefineMarkers(); - void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override; - void DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t yt, Int_t mode, Int_t border, Int_t dark, + void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override; + void DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t yt, Int_t mode, Int_t border, Int_t dark, Int_t light) override; - void DrawHatch(Float_t dy, Float_t angle, Int_t n, Float_t *x, Float_t *y); - void DrawHatch(Float_t dy, Float_t angle, Int_t n, Double_t *x, Double_t *y); - void DrawPolyLine(Int_t n, TPoints *xy); + void DrawHatch(Float_t dy, Float_t angle, Int_t n, Float_t *x, Float_t *y); + void DrawHatch(Float_t dy, Float_t angle, Int_t n, Double_t *x, Double_t *y); + void DrawPolyLine(Int_t n, TPoints *xy); void DrawPolyLineNDC(Int_t n, TPoints *uv); void DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) override; void DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) override; @@ -124,6 +125,8 @@ class TPostScript : public TVirtualPS { void SetLineScale(Float_t scale=3) {fLineScale = scale;} void SetMarkerColor(Color_t cindex=1) override; void SetTextColor(Color_t cindex=1) override; + void SetWidth(Width_t linewidth = 1); + void SetStyle(Style_t linestyle = 1); void MovePS(Int_t x, Int_t y); void Range(Float_t xrange, Float_t yrange); void SetColor(Int_t color = 1); @@ -139,7 +142,7 @@ class TPostScript : public TVirtualPS { Int_t YtoPS(Double_t y); void Zone(); - ClassDefOverride(TPostScript,0) //PostScript driver + ClassDefOverride(TPostScript,1) //PostScript driver }; #endif diff --git a/graf2d/postscript/src/TPostScript.cxx b/graf2d/postscript/src/TPostScript.cxx index 85e14d9e04365..8d4343736d18c 100644 --- a/graf2d/postscript/src/TPostScript.cxx +++ b/graf2d/postscript/src/TPostScript.cxx @@ -275,7 +275,6 @@ TPostScript::TPostScript() : TVirtualPS() fClear = kFALSE; fClip = 0; fClipStatus = kFALSE; - fCurrentColor = 0; fDXC = 0.; fDYC = 0.; fFX = 0.; @@ -301,6 +300,8 @@ TPostScript::TPostScript() : TVirtualPS() fRange = kFALSE; fRed = 0.; fSave = 0; + fWidth = 0.; + fStyle = 1; fX1v = 0.; fX1w = 0.; fX2v = 0.; @@ -361,7 +362,6 @@ void TPostScript::Open(const char *fname, Int_t wtype) } fMarkerSizeCur = 0; - fCurrentColor = 0; fRed = -1; fGreen = -1; fBlue = -1; @@ -944,13 +944,13 @@ void TPostScript::DrawPolyLine(Int_t nn, TPoints *xy) if (nn > 0) { if (fLineWidth<=0) return; n = nn; - SetLineStyle(fLineStyle); - SetLineWidth(fLineWidth); + SetStyle(fLineStyle); + SetWidth(fLineWidth); SetColor(Int_t(fLineColor)); } else { n = -nn; - SetLineStyle(1); - SetLineWidth(1); + SetStyle(1); + SetWidth(1); SetColor(Int_t(fLineColor)); } @@ -1005,8 +1005,8 @@ void TPostScript::DrawPolyLine(Int_t nn, TPoints *xy) } END: if (nn < 0) { - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); } } @@ -1028,13 +1028,13 @@ void TPostScript::DrawPolyLineNDC(Int_t nn, TPoints *xy) if (nn > 0) { if (fLineWidth<=0) return; n = nn; - SetLineStyle(fLineStyle); - SetLineWidth(fLineWidth); + SetStyle(fLineStyle); + SetWidth(fLineWidth); SetColor(Int_t(fLineColor)); } else { n = -nn; - SetLineStyle(1); - SetLineWidth(1); + SetStyle(1); + SetWidth(1); SetColor(Int_t(fLineColor)); } @@ -1089,8 +1089,8 @@ void TPostScript::DrawPolyLineNDC(Int_t nn, TPoints *xy) } END: if (nn < 0) { - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); } } @@ -1107,8 +1107,8 @@ void TPostScript::DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) fMarkerStyle = TMath::Abs(fMarkerStyle); Style_t linestylesav = fLineStyle; Width_t linewidthsav = fLineWidth; - SetLineStyle(1); - SetLineWidth(TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(fMarkerStyle)))); + SetStyle(1); + SetWidth(TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(fMarkerStyle)))); SetColor(Int_t(fMarkerColor)); markerstyle = TAttMarker::GetMarkerStyleBase(fMarkerStyle); if (markerstyle <= 0) strlcpy(chtemp, " m20",10); @@ -1147,8 +1147,8 @@ void TPostScript::DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) WriteInteger(YtoPS(y[0])); if (n == 1) { PrintStr(chtemp); - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); return; } np = 1; @@ -1164,8 +1164,8 @@ void TPostScript::DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) np = 0; } } - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); } //////////////////////////////////////////////////////////////////////////////// @@ -1181,8 +1181,8 @@ void TPostScript::DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) fMarkerStyle = TMath::Abs(fMarkerStyle); Style_t linestylesav = fLineStyle; Width_t linewidthsav = fLineWidth; - SetLineStyle(1); - SetLineWidth(TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(fMarkerStyle)))); + SetStyle(1); + SetWidth(TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(fMarkerStyle)))); SetColor(Int_t(fMarkerColor)); markerstyle = TAttMarker::GetMarkerStyleBase(fMarkerStyle); if (markerstyle <= 0) strlcpy(chtemp, " m20",10); @@ -1221,8 +1221,8 @@ void TPostScript::DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) WriteInteger(YtoPS(y[0])); if (n == 1) { PrintStr(chtemp); - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); return; } np = 1; @@ -1238,8 +1238,8 @@ void TPostScript::DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) np = 0; } } - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); } //////////////////////////////////////////////////////////////////////////////// @@ -1270,14 +1270,14 @@ void TPostScript::DrawPS(Int_t nn, Float_t *xw, Float_t *yw) if (nn > 0) { if (fLineWidth<=0) return; n = nn; - SetLineStyle(fLineStyle); - SetLineWidth(fLineWidth); + SetStyle(fLineStyle); + SetWidth(fLineWidth); SetColor(Int_t(fLineColor)); } if (nn < 0) { n = -nn; - SetLineStyle(1); - SetLineWidth(1); + SetStyle(1); + SetWidth(1); SetColor(Int_t(fFillColor)); fais = fFillStyle/1000; fasi = fFillStyle%1000; @@ -1348,8 +1348,8 @@ void TPostScript::DrawPS(Int_t nn, Float_t *xw, Float_t *yw) } END: if (nn < 0) { - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); } } @@ -1381,14 +1381,14 @@ void TPostScript::DrawPS(Int_t nn, Double_t *xw, Double_t *yw) if (nn > 0) { if (fLineWidth<=0) return; n = nn; - SetLineStyle(fLineStyle); - SetLineWidth(fLineWidth); + SetStyle(fLineStyle); + SetWidth(fLineWidth); SetColor(Int_t(fLineColor)); } if (nn < 0) { n = -nn; - SetLineStyle(1); - SetLineWidth(1); + SetStyle(1); + SetWidth(1); SetColor(Int_t(fFillColor)); fais = fFillStyle/1000; fasi = fFillStyle%1000; @@ -1459,8 +1459,8 @@ void TPostScript::DrawPS(Int_t nn, Double_t *xw, Double_t *yw) } END: if (nn < 0) { - SetLineStyle(linestylesav); - SetLineWidth(linewidthsav); + SetStyle(linestylesav); + SetWidth(linewidthsav); } } @@ -2129,7 +2129,6 @@ void TPostScript::SetFillColor( Color_t cindex ) { fFillColor = cindex; if (gStyle->GetFillColor() <= 0) cindex = 0; - SetColor(Int_t(cindex)); } //////////////////////////////////////////////////////////////////////////////// @@ -2461,7 +2460,6 @@ void TPostScript::SetFillPatterns(Int_t ipat, Int_t color) void TPostScript::SetLineColor( Color_t cindex ) { fLineColor = cindex; - SetColor(Int_t(cindex)); } //////////////////////////////////////////////////////////////////////////////// @@ -2526,7 +2524,18 @@ void TPostScript::SetLineStyle(Style_t linestyle) { if ( linestyle == fLineStyle) return; fLineStyle = linestyle; - const char *st = gStyle->GetLineStyleString(linestyle); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Change the line style in the output file + +void TPostScript::SetStyle(Style_t linestyle) +{ + if (linestyle == fStyle) return; + + fStyle = linestyle; + + const char *st = gStyle->GetLineStyleString(fStyle); PrintFast(1,"["); Int_t nch = strlen(st); PrintFast(nch,st); @@ -2538,10 +2547,21 @@ void TPostScript::SetLineStyle(Style_t linestyle) void TPostScript::SetLineWidth(Width_t linewidth) { - if ( linewidth == fLineWidth) return; + if (linewidth == fLineWidth) return; fLineWidth = linewidth; - if (fLineWidth!=0) { - WriteInteger(Int_t(fLineScale*fLineWidth)); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Change the line width in the output file + +void TPostScript::SetWidth(Width_t linewidth) +{ + if (linewidth == fWidth) return; + + fWidth = linewidth; + + if (fWidth!=0) { + WriteInteger(Int_t(fLineScale*fWidth)); PrintFast(3," lw"); } } @@ -2552,7 +2572,6 @@ void TPostScript::SetLineWidth(Width_t linewidth) void TPostScript::SetMarkerColor( Color_t cindex ) { fMarkerColor = cindex; - SetColor(Int_t(cindex)); } //////////////////////////////////////////////////////////////////////////////// @@ -2561,7 +2580,6 @@ void TPostScript::SetMarkerColor( Color_t cindex ) void TPostScript::SetColor(Int_t color) { if (color < 0) color = 0; - fCurrentColor = color; TColor *col = gROOT->GetColor(color); if (col) SetColor(col->GetRed(), col->GetGreen(), col->GetBlue()); @@ -2607,8 +2625,6 @@ void TPostScript::SetColor(Float_t r, Float_t g, Float_t b) void TPostScript::SetTextColor( Color_t cindex ) { fTextColor = cindex; - - SetColor( Int_t(cindex) ); } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/quartz/inc/QuartzFillArea.h b/graf2d/quartz/inc/QuartzFillArea.h index 73f88b6bedbe9..ab3b0caee21a1 100644 --- a/graf2d/quartz/inc/QuartzFillArea.h +++ b/graf2d/quartz/inc/QuartzFillArea.h @@ -22,21 +22,21 @@ #include -#include "TAttFill.h" #include "Rtypes.h" #include "TPoint.h" class TColorGradient; +class TAttFill; namespace ROOT { namespace Quartz { Bool_t SetFillColor(CGContextRef ctx, Color_t colorIndex); -Bool_t SetFillAreaParameters(CGContextRef ctx, unsigned *patternIndex); +Bool_t SetFillAreaParameters(CGContextRef ctx, unsigned *patternIndex, const TAttFill &attfill); void DrawBox(CGContextRef ctx, Int_t x1, Int_t y1, Int_t x2, Int_t y2, bool hollow); -void DrawFillArea(CGContextRef ctx, Int_t n, TPoint *xy, Bool_t drawShadow); +void DrawFillArea(CGContextRef ctx, Int_t n, TPoint *xy, Bool_t drawShadow, const TAttFill &attfill); void DrawPolygonWithGradientFill(CGContextRef ctx, const TColorGradient *extendedColor, const CGSize &sizeOfDrawable, Int_t nPoints, const TPoint *xy, Bool_t drawShadow); diff --git a/graf2d/quartz/inc/QuartzText.h b/graf2d/quartz/inc/QuartzText.h index e0c3014ab3f4b..b6ff70bfb9072 100644 --- a/graf2d/quartz/inc/QuartzText.h +++ b/graf2d/quartz/inc/QuartzText.h @@ -20,6 +20,8 @@ #include "GuiTypes.h" +class TAttText; + ///////////////////////////////////////////////// // // // TextLine - wrapper class for a CoreText's // @@ -48,8 +50,8 @@ class TextLine { void GetBounds(UInt_t &w, UInt_t &h)const; void GetAscentDescent(Int_t &asc, Int_t &desc)const; - void DrawLine(CGContextRef ctx)const; - void DrawLine(CGContextRef ctx, Double_t x, Double_t y)const; + void DrawLine(CGContextRef ctx) const; + void DrawLine(CGContextRef ctx, Double_t x, Double_t y, const TAttText &att) const; private: CTLineRef fCTLine; //Core Text line, created from Attributed string. CTFontRef fCTFont; //A font used for this CTLine. diff --git a/graf2d/quartz/src/QuartzFillArea.mm b/graf2d/quartz/src/QuartzFillArea.mm index 3114e2d7132be..0818d416a30d1 100644 --- a/graf2d/quartz/src/QuartzFillArea.mm +++ b/graf2d/quartz/src/QuartzFillArea.mm @@ -15,9 +15,9 @@ #include "QuartzFillArea.h" #include "TColorGradient.h" +#include "TAttFill.h" #include "QuartzLine.h" #include "CocoaUtils.h" -#include "TVirtualX.h" #include "RStipples.h" #include "TError.h" #include "TROOT.h" @@ -347,12 +347,12 @@ void DrawPattern(void *data, CGContextRef ctx) } //______________________________________________________________________________ -bool SetFillPattern(CGContextRef ctx, const unsigned *patternIndex) +bool SetFillPattern(CGContextRef ctx, const unsigned *patternIndex, Color_t attrFillColor) { assert(ctx != nullptr && "SetFillPattern, ctx parameter is null"); assert(patternIndex != nullptr && "SetFillPattern, patternIndex parameter is null"); - const TColor *fillColor = gROOT->GetColor(gVirtualX->GetFillColor()); + const TColor *fillColor = gROOT->GetColor(attrFillColor); if (!fillColor) fillColor = gROOT->GetColor(kWhite); @@ -388,33 +388,36 @@ bool SetFillPattern(CGContextRef ctx, const unsigned *patternIndex) } //______________________________________________________________________________ -bool SetFillAreaParameters(CGContextRef ctx, unsigned *patternIndex) +bool SetFillAreaParameters(CGContextRef ctx, unsigned *patternIndex, const TAttFill &attfill) { assert(ctx != nullptr && "SetFillAreaParameters, ctx parameter is null"); - const unsigned fillStyle = gVirtualX->GetFillStyle() / 1000; + Style_t attFillStyle = attfill.GetFillStyle(); + Color_t attFillColor = attfill.GetFillColor(); + + const unsigned fillStyle = attFillStyle / 1000; //2 is hollow, 1 is solid and 3 is a hatch, !solid and !hatch - this is from O.C.'s code. if (fillStyle == 2 || (fillStyle != 1 && fillStyle != 3)) { - if (!SetLineColor(ctx, gVirtualX->GetFillColor())) { - ::Error("SetFillAreaParameters", "Line color for index %d was not found", int(gVirtualX->GetLineColor())); + if (!SetLineColor(ctx, attFillColor)) { + ::Error("SetFillAreaParameters", "Line color for index %d was not found", int(attFillColor)); return false; } } else if (fillStyle == 1) { //Solid fill. - if (!SetFillColor(ctx, gVirtualX->GetFillColor())) { - ::Error("SetFillAreaParameters", "Fill color for index %d was not found", int(gVirtualX->GetFillColor())); + if (!SetFillColor(ctx, attFillColor)) { + ::Error("SetFillAreaParameters", "Fill color for index %d was not found", int(attFillColor)); return false; } } else { assert(patternIndex != nullptr && "SetFillAreaParameters, pattern index in null"); - *patternIndex = gVirtualX->GetFillStyle() % 1000; + *patternIndex = attFillStyle % 1000; //ROOT has 26 fixed patterns. if (*patternIndex > 25) *patternIndex = 2; - if (!SetFillPattern(ctx, patternIndex)) { + if (!SetFillPattern(ctx, patternIndex, attFillColor)) { ::Error("SetFillAreaParameters", "SetFillPattern failed"); return false; } @@ -440,7 +443,7 @@ void DrawBox(CGContextRef ctx, Int_t x1, Int_t y1, Int_t x2, Int_t y2, bool holl } //______________________________________________________________________________ -void DrawFillArea(CGContextRef ctx, Int_t n, TPoint *xy, Bool_t shadow) +void DrawFillArea(CGContextRef ctx, Int_t n, TPoint *xy, Bool_t shadow, const TAttFill &attfill) { // Draw a filled area through all points. // n : number of points @@ -457,7 +460,7 @@ void DrawFillArea(CGContextRef ctx, Int_t n, TPoint *xy, Bool_t shadow) CGContextClosePath(ctx); - const unsigned fillStyle = gVirtualX->GetFillStyle() / 1000; + const unsigned fillStyle = attfill.GetFillStyle() / 1000; //2 is hollow, 1 is solid and 3 is a hatch, !solid and !hatch - this is from O.C.'s code. if (fillStyle == 2 || (fillStyle != 1 && fillStyle != 3)) { diff --git a/graf2d/quartz/src/QuartzText.mm b/graf2d/quartz/src/QuartzText.mm index 1da812a09aeaa..a38beede91343 100644 --- a/graf2d/quartz/src/QuartzText.mm +++ b/graf2d/quartz/src/QuartzText.mm @@ -18,7 +18,7 @@ #include "QuartzText.h" #include "CocoaUtils.h" -#include "TVirtualX.h" +#include "TAttText.h" #include "TColor.h" #include "TError.h" #include "TROOT.h" @@ -264,7 +264,7 @@ CGRect BBoxForCTRun(CTFontRef font, CTRunRef run) } //_________________________________________________________________ -void TextLine::DrawLine(CGContextRef ctx)const +void TextLine::DrawLine(CGContextRef ctx) const { assert(ctx != 0 && "DrawLine, ctx parameter is null"); CTLineDraw(fCTLine, ctx); @@ -272,7 +272,7 @@ CGRect BBoxForCTRun(CTFontRef font, CTRunRef run) //______________________________________________________________________________ -void TextLine::DrawLine(CGContextRef ctx, Double_t x, Double_t y)const +void TextLine::DrawLine(CGContextRef ctx, Double_t x, Double_t y, const TAttText &att) const { assert(ctx != 0 && "DrawLine, ctx parameter is null"); @@ -282,7 +282,7 @@ CGRect BBoxForCTRun(CTFontRef font, CTRunRef run) GetBounds(w, h); Double_t xc = 0., yc = 0.; - const UInt_t hAlign = UInt_t(gVirtualX->GetTextAlign() / 10); + Int_t hAlign = att.GetTextAlign() / 10; switch (hAlign) { case 1: xc = 0.5 * w; @@ -294,7 +294,7 @@ CGRect BBoxForCTRun(CTFontRef font, CTRunRef run) break; } - const UInt_t vAlign = UInt_t(gVirtualX->GetTextAlign() % 10); + Int_t vAlign = att.GetTextAlign() % 10; switch (vAlign) { case 1: yc = 0.5 * h; @@ -308,7 +308,7 @@ CGRect BBoxForCTRun(CTFontRef font, CTRunRef run) CGContextSetTextPosition(ctx, 0., 0.); CGContextTranslateCTM(ctx, x, y); - CGContextRotateCTM(ctx, gVirtualX->GetTextAngle() * TMath::DegToRad()); + CGContextRotateCTM(ctx, att.GetTextAngle() * TMath::DegToRad()); CGContextTranslateCTM(ctx, xc, yc); CGContextTranslateCTM(ctx, -0.5 * w, -0.5 * h); diff --git a/graf2d/win32gdk/CMakeLists.txt b/graf2d/win32gdk/CMakeLists.txt index c25610240fa93..fefd4b9b3387a 100644 --- a/graf2d/win32gdk/CMakeLists.txt +++ b/graf2d/win32gdk/CMakeLists.txt @@ -10,8 +10,7 @@ ############################################################################ # use relative paths to avoid filtering in dictionary generator -include_directories(${FREETYPE_INCLUDE_DIRS} - ${CMAKE_CURRENT_SOURCE_DIR}/gdk/src +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gdk/src ${CMAKE_CURRENT_SOURCE_DIR}/gdk/src/gdk ${CMAKE_CURRENT_SOURCE_DIR}/gdk/src/glib) @@ -117,7 +116,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Win32gdk DICTIONARY_OPTIONS -writeEmptyRootPCM LIBRARIES - ${FREETYPE_LIBRARIES} + Freetype::Freetype ${gdklib} ${gliblib} Glu32.lib diff --git a/graf2d/win32gdk/inc/TGWin32.h b/graf2d/win32gdk/inc/TGWin32.h index ef6e849267bb9..43c0a92aebac7 100644 --- a/graf2d/win32gdk/inc/TGWin32.h +++ b/graf2d/win32gdk/inc/TGWin32.h @@ -17,6 +17,10 @@ #include "TTF.h" +#include +#include + + #ifndef __CLING__ @@ -64,31 +68,24 @@ class TExMap; class TGWin32 : public TVirtualX { private: - enum EAlign { kNone, kTLeft, kTCenter, kTRight, kMLeft, kMCenter, kMRight, - kBLeft, kBCenter, kBRight }; - - FT_Vector fAlign; ///< alignment vector - - void Align(void); + void Align(WinContext_t wctxt); void DrawImage(FT_Bitmap *source, ULong_t fore, ULong_t back, GdkImage *xim, Int_t bx, Int_t by); - Bool_t IsVisible(Int_t x, Int_t y, UInt_t w, UInt_t h); - GdkImage *GetBackground(Int_t x, Int_t y, UInt_t w, UInt_t h); - void RenderString(Int_t x, Int_t y, ETextMode mode); + Bool_t IsVisible(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h); + GdkImage *GetBackground(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h); + void RenderString(WinContext_t wctxt, Int_t x, Int_t y, ETextMode mode); - Int_t fMaxNumberOfWindows; ///< Maximum number of windows - XWindow_t *fWindows; ///< List of windows + std::unordered_map> fWindows; // map of windows TExMap *fColors; ///< Hash list of colors GdkCursor *fCursors[kNumCursors]; ///< List of cursors - void CloseWindow1(); + Int_t AddWindowHandle(); void PutImage(Int_t offset, Int_t itran, Int_t x0, Int_t y0, Int_t nx, Int_t ny, Int_t xmin, Int_t ymin, Int_t xmax, Int_t ymax, UChar_t *image, Drawable_t id); void RemovePixmap(GdkDrawable *pix); - void SetColor(GdkGC *gc, Int_t ci); + void SetColor(XWindow_t *ctxt, GdkGC *gc, Int_t ci); void SetInput(Int_t inp); - void SetMarkerType(Int_t type, Int_t n, GdkPoint *xy); void MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors); Int_t FindColor(ULong_t pixel, ULong_t *orgcolors, Int_t ncolors); void ImgPickPalette(GdkImage *image, Int_t &ncol, Int_t *&R, Int_t *&G, Int_t *&B); @@ -110,9 +107,6 @@ class TGWin32 : public TVirtualX { Int_t fScreenNumber; ///< Screen number Bool_t fHasTTFonts; ///< True when TrueType fonts are used Bool_t fUseSysPointers; ///< True when using system mouse pointers - Int_t fTextAlignH; ///< Text Alignment Horizontal - Int_t fTextAlignV; ///< Text Alignment Vertical - Int_t fTextAlign; ///< Text alignment (set in SetTextAlign) Float_t fCharacterUpX; ///< Character Up vector along X Float_t fCharacterUpY; ///< Character Up vector along Y Float_t fTextMagnitude; ///< Text Magnitude @@ -126,20 +120,6 @@ class TGWin32 : public TVirtualX { Handle_t fXEvent; ///< Current native (GDK) event TObject* fRefreshTimer; ///< TGWin32RefreshTimer for GUI thread message handler - Bool_t fFillColorModified; - Bool_t fFillStyleModified; - Bool_t fLineColorModified; - Bool_t fPenModified; ///< line syle || width modified - Bool_t fMarkerStyleModified; - Bool_t fMarkerColorModified; - - void UpdateFillColor(); - void UpdateFillStyle(); - void UpdateLineColor(); - void UpdateMarkerStyle(); - void UpdateMarkerColor(); - void UpdateLineStyle(); - // needed by TGWin32TTF Bool_t AllocColor(GdkColormap *cmap, GdkColor *color); void QueryColors(GdkColormap *cmap, GdkColor *colors, Int_t ncolors); @@ -205,10 +185,13 @@ class TGWin32 : public TVirtualX { void SetDrawMode(EDrawMode mode) override; void SetFillColor(Color_t cindex) override; void SetFillStyle(Style_t style) override; + Style_t GetFillStyle() const override; void SetLineColor(Color_t cindex) override; void SetLineType(Int_t n, Int_t *dash) override; void SetLineStyle(Style_t linestyle) override; + Style_t GetLineStyle() const override; void SetLineWidth(Width_t width) override; + Width_t GetLineWidth() const override; void SetMarkerColor(Color_t cindex) override; void SetMarkerSize(Float_t markersize) override; void SetMarkerStyle(Style_t markerstyle) override; @@ -224,6 +207,28 @@ class TGWin32 : public TVirtualX { void WritePixmap(Int_t wid, UInt_t w, UInt_t h, char *pxname) override; Window_t GetCurrentWindow() const override; + //---- Methods used for new graphics ----- + WinContext_t GetWindowContext(Int_t wid) override; + void SetAttFill(WinContext_t wctxt, const TAttFill &att) override; + void SetAttLine(WinContext_t wctxt, const TAttLine &att) override; + void SetAttMarker(WinContext_t wctxt, const TAttMarker &att) override; + void SetAttText(WinContext_t wctxt, const TAttText &att) override; + void SetDrawModeW(WinContext_t wctxt, EDrawMode mode) override; + EDrawMode GetDrawModeW(WinContext_t wctxt) override; + void ClearWindowW(WinContext_t wctxt) override; + void UpdateWindowW(WinContext_t wctxt, Int_t mode) override; + + void DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) override; + void DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2) override; + void DrawPolyLineW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const char *text, ETextMode mode) override; + void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const wchar_t *text, ETextMode mode) override; + //---- Methods used for GUI ----- void GetWindowAttributes(Window_t id, WindowAttributes_t &attr) override; void MapWindow(Window_t id) override; diff --git a/graf2d/win32gdk/src/TGWin32.cxx b/graf2d/win32gdk/src/TGWin32.cxx index 4ae85c959c7a6..9931b6b7f54c7 100644 --- a/graf2d/win32gdk/src/TGWin32.cxx +++ b/graf2d/win32gdk/src/TGWin32.cxx @@ -116,24 +116,53 @@ void gdk_win32_draw_lines (GdkDrawable *drawable, }; +enum EAlign { kAlignNone, kTLeft, kTCenter, kTRight, kMLeft, kMCenter, kMRight, + kBLeft, kBCenter, kBRight }; + +const int kMAXGC = 7, + kGCline = 0, kGCmark = 1, kGCfill = 2, + kGCtext = 3, kGCinvt = 4, kGCdash = 5, kGCpxmp = 6; + + //////////// internal classes & structures (very private) //////////////// struct XWindow_t { - Int_t open; // 1 if the window is open, 0 if not - Int_t double_buffer; // 1 if the double buffer is on, 0 if not - Int_t ispixmap; // 1 if pixmap, 0 if not - GdkDrawable *drawing; // drawing area, equal to window or buffer - GdkDrawable *window; // win32 window - GdkDrawable *buffer; // pixmap used for double buffer - UInt_t width; // width of the window - UInt_t height; // height of the window - Int_t clip; // 1 if the clipping is on - Int_t xclip; // x coordinate of the clipping rectangle - Int_t yclip; // y coordinate of the clipping rectangle - UInt_t wclip; // width of the clipping rectangle - UInt_t hclip; // height of the clipping rectangle - ULong_t *new_colors; // new image colors (after processing) - Int_t ncolors; // number of different colors + Int_t open = 0; ///< 1 if the window is open, 0 if not + Int_t shared = 0; ///< 1 if Qt window + Int_t double_buffer = 0; ///< 1 if the double buffer is on, 0 if not + Int_t ispixmap = 0; ///< 1 if pixmap, 0 if not + GdkDrawable *drawing = nullptr;///< drawing area, equal to window or buffer + GdkDrawable *window = nullptr; ///< win32 window + GdkDrawable *buffer = nullptr; ///< pixmap used for double buffer + UInt_t width = 0; ///< width of the window + UInt_t height = 0; ///< height of the window + Int_t clip = 0; ///< 1 if the clipping is on + Int_t xclip = 0; ///< x coordinate of the clipping rectangle + Int_t yclip = 0; ///< y coordinate of the clipping rectangle + UInt_t wclip = 0; ///< width of the clipping rectangle + UInt_t hclip = 0; ///< height of the clipping rectangle + ULong_t *new_colors = nullptr; ///< new image colors (after processing) + Int_t ncolors = 0; ///< number of different colors + GdkGC *fGClist[kMAXGC]; ///< array of GC objects for concrete window + TVirtualX::EDrawMode drawMode = TVirtualX::kCopy; ///< current draw mode + TAttLine fAttLine = {-1, -1, -1}; ///< current line attributes + GdkLineStyle lineStyle = GDK_LINE_SOLID; ///< current line style + Int_t lineWidth = 0; ///< current line width + std::vector dashList; ///< Gtk array for dashes + Int_t dashLength = 0; ///< total length of dashes + Int_t dashOffset = 0; ///< current dash offset + TAttFill fAttFill = {-1, -1}; ///< current fill attributes + Int_t fillHollow = 0; ///< Flag if fill style is hollow + Int_t fillFasi = -1; ///< fasi parameter for fill pattern + GdkPixmap *fillPattern = nullptr; ///< current fill pattern + TAttMarker fAttMarker = { -1, -1, -1 }; ///< current marker attribute + Int_t markerType = 0; ///< 4 differen kinds of marker + Int_t markerSize = 0; ///< size of simple markers + std::vector markerShape; ///< marker shape points + Int_t markerLineWidth = 0; ///< line width used for marker + TAttText fAttText; ///< current text attributes + EAlign textAlign = kAlignNone; ///< selected text align + FT_Vector alignVector; ///< alignment vector }; @@ -147,35 +176,9 @@ GdkAtom gClipboardAtom = GDK_NONE; static XWindow_t *gCws; // gCws: pointer to the current window static XWindow_t *gTws; // gTws: temporary pointer -// -// gColors[0] : background also used for b/w screen -// gColors[1] : foreground also used for b/w screen -// gColors[2..kMAXCOL-1]: colors which can be set by SetColor -// const Int_t kBIGGEST_RGB_VALUE = 65535; -//const Int_t kMAXCOL = 1000; -//static struct { -// Int_t defined; -// GdkColor color; -//} gColors[kMAXCOL]; - -// -// Primitives Graphic Contexts global for all windows -// -const int kMAXGC = 7; -static GdkGC *gGClist[kMAXGC]; -static GdkGC *gGCline; // = gGClist[0]; // PolyLines -static GdkGC *gGCmark; // = gGClist[1]; // PolyMarker -static GdkGC *gGCfill; // = gGClist[2]; // Fill areas -static GdkGC *gGCtext; // = gGClist[3]; // Text -static GdkGC *gGCinvt; // = gGClist[4]; // Inverse text -static GdkGC *gGCdash; // = gGClist[5]; // Dashed lines -static GdkGC *gGCpxmp; // = gGClist[6]; // Pixmap management - -static GdkGC *gGCecho; // Input echo -static Int_t gFillHollow; // Flag if fill style is hollow -static GdkPixmap *gFillPattern; // Fill pattern +static GdkGC *gGCecho; // Input echo - global // // Text management @@ -185,13 +188,6 @@ static const char *gTextFont = "arial.ttf"; // Current font // // Markers // -const Int_t kMAXMK = 100; -static struct { - int type; - int n; - GdkPoint xy[kMAXMK]; -} gMarker; // Point list to draw marker -static int gMarkerLineWidth = 0; static int gMarkerLineStyle = GDK_LINE_SOLID; static int gMarkerCapStyle = GDK_CAP_ROUND; static int gMarkerJoinStyle = GDK_JOIN_ROUND; @@ -199,14 +195,8 @@ static int gMarkerJoinStyle = GDK_JOIN_ROUND; // // Keep style values for line GdkGC // -static int gLineWidth = 0; -static int gLineStyle = GDK_LINE_SOLID; static int gCapStyle = GDK_CAP_BUTT; static int gJoinStyle = GDK_JOIN_MITER; -static char gDashList[10]; -static int gDashLength = 0; -static int gDashOffset = 0; -static int gDashSize = 0; // // Event masks @@ -810,7 +800,6 @@ TGWin32MainThread::TGWin32MainThread() TGWin32::TGWin32(): fRefreshTimer(0) { fScreenNumber = 0; - fWindows = 0; fColors = 0; } @@ -822,25 +811,11 @@ TGWin32::TGWin32(const char *name, const char *title) : TVirtualX(name,title), f fScreenNumber = 0; fHasTTFonts = kFALSE; fUseSysPointers = kFALSE; - fTextAlignH = 1; - fTextAlignV = 1; - fTextAlign = 7; fTextMagnitude = 1; fCharacterUpX = 1; fCharacterUpY = 1; fDrawMode = kCopy; - fWindows = 0; - fMaxNumberOfWindows = 10; fXEvent = 0; - fFillColorModified = kFALSE; - fFillStyleModified = kFALSE; - fLineColorModified = kFALSE; - fPenModified = kFALSE; - fMarkerStyleModified = kFALSE; - fMarkerColorModified = kFALSE; - - fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t)); - for (int i = 0; i < fMaxNumberOfWindows; i++) fWindows[i].open = 0; fColors = new TExMap; @@ -921,9 +896,6 @@ void TGWin32::CloseDisplay() delete delSplash; } - if (fWindows) TStorage::Dealloc(fWindows); - fWindows = 0; - if (fXEvent) gdk_event_free((GdkEvent*)fXEvent); TGWin32ProxyBase::GlobalUnlock(); @@ -972,7 +944,6 @@ Int_t TGWin32::OpenDisplay(const char *dpyName) GdkPixmap *pixmp1, *pixmp2; GdkColor fore, back; GdkColor color; - GdkGCValues gcvals; int i; HWND hDesktop = ::GetDesktopWindow(); @@ -1004,25 +975,6 @@ Int_t TGWin32::OpenDisplay(const char *dpyName) GetColor(0).fDefined = kTRUE; // default background gdk_color_white((GdkColormap *)fColormap, &GetColor(0).color); - // Create primitives graphic contexts - for (i = 0; i < kMAXGC; i++) { - gGClist[i] = gdk_gc_new(GDK_ROOT_PARENT()); - gdk_gc_set_foreground(gGClist[i], &GetColor(1).color); - gdk_gc_set_background(gGClist[i], &GetColor(0).color); - } - - gGCline = gGClist[0]; // PolyLines - gGCmark = gGClist[1]; // PolyMarker - gGCfill = gGClist[2]; // Fill areas - gGCtext = gGClist[3]; // Text - gGCinvt = gGClist[4]; // Inverse text - gGCdash = gGClist[5]; // Dashed lines - gGCpxmp = gGClist[6]; // Pixmap management - - gdk_gc_get_values(gGCtext, &gcvals); - gdk_gc_set_foreground(gGCinvt, &gcvals.background); - gdk_gc_set_background(gGCinvt, &gcvals.foreground); - // Create input echo graphic context GdkGCValues echov; gdk_color_black(fColormap, &echov.foreground); // = BlackPixel(fDisplay, fScreenNumber); @@ -1199,30 +1151,32 @@ void TGWin32::QueryColors(GdkColormap *cmap, GdkColor *color, Int_t ncolors) /// then the rotation is applied on the alignment variables. /// SetRotation and LayoutGlyphs should have been called before. -void TGWin32::Align(void) +void TGWin32::Align(WinContext_t wctxt) { - EAlign align = (EAlign) fTextAlign; + auto ctxt = (XWindow_t *) wctxt; + + auto align = ctxt->textAlign; // vertical alignment if (align == kTLeft || align == kTCenter || align == kTRight) { - fAlign.y = TTF::GetAscent(); + ctxt->alignVector.y = TTF::GetAscent(); } else if (align == kMLeft || align == kMCenter || align == kMRight) { - fAlign.y = TTF::GetAscent()/2; + ctxt->alignVector.y = TTF::GetAscent()/2; } else { - fAlign.y = 0; + ctxt->alignVector.y = 0; } // horizontal alignment if (align == kTRight || align == kMRight || align == kBRight) { - fAlign.x = TTF::GetWidth(); + ctxt->alignVector.x = TTF::GetWidth(); } else if (align == kTCenter || align == kMCenter || align == kBCenter) { - fAlign.x = TTF::GetWidth()/2; + ctxt->alignVector.x = TTF::GetWidth()/2; } else { - fAlign.x = 0; + ctxt->alignVector.x = 0; } - FT_Vector_Transform(&fAlign, TTF::GetRotMatrix()); - fAlign.x = fAlign.x >> 6; - fAlign.y = fAlign.y >> 6; + FT_Vector_Transform(&ctxt->alignVector, TTF::GetRotMatrix()); + ctxt->alignVector.x = ctxt->alignVector.x >> 6; + ctxt->alignVector.y = ctxt->alignVector.y >> 6; } //////////////////////////////////////////////////////////////////////////////// @@ -1352,12 +1306,25 @@ void TGWin32::DrawImage(FT_Bitmap *source, ULong_t fore, ULong_t back, void TGWin32::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) { + DrawTextW((WinContext_t) gCws, x, y, angle, mgn, text, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw text using TrueType fonts on specified window. +/// If TrueType fonts are not available the +/// text is drawn with TGWin32::DrawText. + +void TGWin32::DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const char *text, ETextMode mode) +{ + if (!wctxt) return; + if (!TTF::IsInitialized()) TTF::Init(); TTF::SetRotationMatrix(angle); TTF::PrepareString(text); TTF::LayoutGlyphs(); - Align(); - RenderString(x, y, mode); + Align(wctxt); + RenderString(wctxt, x, y, mode); } //////////////////////////////////////////////////////////////////////////////// @@ -1367,24 +1334,38 @@ void TGWin32::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, void TGWin32::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode) { + DrawTextW((WinContext_t) gCws, x, y, angle, mgn, text, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw text using TrueType fonts on specified window. +/// If TrueType fonts are not available the +/// text is drawn with TGWin32::DrawText. + +void TGWin32::DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const wchar_t *text, ETextMode mode) +{ + if (!wctxt) return; + if (!TTF::IsInitialized()) TTF::Init(); TTF::SetRotationMatrix(angle); TTF::PrepareString(text); TTF::LayoutGlyphs(); - Align(); - RenderString(x, y, mode); + Align(wctxt); + RenderString(wctxt, x, y, mode); } //////////////////////////////////////////////////////////////////////////////// /// Get the background of the current window in an XImage. -GdkImage *TGWin32::GetBackground(Int_t x, Int_t y, UInt_t w, UInt_t h) +GdkImage *TGWin32::GetBackground(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h) { - Window_t cws = GetCurrentWindow(); + auto ctxt = (XWindow_t *) wctxt; + UInt_t width; UInt_t height; Int_t xy; - gVirtualX->GetWindowSize(cws, xy, xy, width, height); + GetWindowSize((Drawable_t) ctxt->drawing, xy, xy, width, height); if (x < 0) { w += x; @@ -1398,19 +1379,20 @@ GdkImage *TGWin32::GetBackground(Int_t x, Int_t y, UInt_t w, UInt_t h) if (x+w > width) w = width - x; if (y+h > height) h = height - y; - return gdk_image_get((GdkDrawable*)cws, x, y, w, h); + return gdk_image_get(ctxt->drawing, x, y, w, h); } //////////////////////////////////////////////////////////////////////////////// /// Test if there is really something to render -Bool_t TGWin32::IsVisible(Int_t x, Int_t y, UInt_t w, UInt_t h) +Bool_t TGWin32::IsVisible(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h) { - Window_t cws = GetCurrentWindow(); + auto ctxt = (XWindow_t *) wctxt; + UInt_t width; UInt_t height; Int_t xy; - gVirtualX->GetWindowSize(cws, xy, xy, width, height); + GetWindowSize((Drawable_t) ctxt->drawing, xy, xy, width, height); // If w or h is 0, very likely the string is only blank characters if ((int)w == 0 || (int)h == 0) return kFALSE; @@ -1426,8 +1408,10 @@ Bool_t TGWin32::IsVisible(Int_t x, Int_t y, UInt_t w, UInt_t h) /// Perform the string rendering in the pad. /// LayoutGlyphs should have been called before. -void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode) +void TGWin32::RenderString(WinContext_t wctxt, Int_t x, Int_t y, ETextMode mode) { + auto ctxt = (XWindow_t *) wctxt; + TTF::TTGlyph* glyph = TTF::GetGlyphs(); GdkGCValues gcvals; @@ -1436,10 +1420,10 @@ void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode) Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin; Int_t w = TTF::GetBox().xMax + Xoff; Int_t h = TTF::GetBox().yMax + Yoff; - Int_t x1 = x-Xoff-fAlign.x; - Int_t y1 = y+Yoff+fAlign.y-h; + Int_t x1 = x - Xoff - ctxt->alignVector.x; + Int_t y1 = y + Yoff + ctxt->alignVector.y - h; - if (!IsVisible(x1, y1, w, h)) { + if (!IsVisible(wctxt, x1, y1, w, h)) { return; } @@ -1454,12 +1438,12 @@ void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode) ULong_t pixel; ULong_t bg; - gdk_gc_get_values((GdkGC*)GetGC(3), &gcvals); + gdk_gc_get_values(ctxt->fGClist[kGCtext], &gcvals); // get the background if (mode == kClear) { // if mode == kClear we need to get an image of the background - GdkImage *bim = GetBackground(x1, y1, w, h); + GdkImage *bim = GetBackground(wctxt, x1, y1, w, h); if (!bim) { Error("DrawText", "error getting background image"); return; @@ -1483,7 +1467,7 @@ void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode) } else { // if mode == kOpaque its simple, we just draw the background - GdkImage *bim = GetBackground(x1, y1, w, h); + GdkImage *bim = GetBackground(wctxt, x1, y1, w, h); if (!bim) { pixel = gcvals.background.pixel; } else { @@ -1523,8 +1507,7 @@ void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode) } // put the Ximage on the screen - Window_t cws = GetCurrentWindow(); - gdk_draw_image((GdkDrawable *)cws, GetGC(6), xim, 0, 0, x1, y1, w, h); + gdk_draw_image(ctxt->drawing, ctxt->fGClist[kGCpxmp], xim, 0, 0, x1, y1, w, h); gdk_image_unref(xim); } @@ -1534,8 +1517,12 @@ void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode) void TGWin32::SetTextFont(Font_t fontnumber) { - fTextFont = fontnumber; - TTF::SetTextFont(fontnumber); + TAttText::SetTextFont(fontnumber); + + TAttText arg(gCws->fAttText); + arg.SetTextFont(fontnumber); + + SetAttText((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -1548,7 +1535,7 @@ void TGWin32::SetTextFont(Font_t fontnumber) /// Set text font to specified name. This function returns 0 if /// the specified font is found, 1 if not. -Int_t TGWin32::SetTextFont(char *fontname, ETextSetMode mode) +Int_t TGWin32::SetTextFont(char *fontname, ETextSetMode /* mode */) { return TTF::SetTextFont(fontname); } @@ -1558,8 +1545,12 @@ Int_t TGWin32::SetTextFont(char *fontname, ETextSetMode mode) void TGWin32::SetTextSize(Float_t textsize) { - fTextSize = textsize; - TTF::SetTextSize(textsize); + TAttText::SetTextSize(textsize); + + TAttText arg(gCws->fAttText); + arg.SetTextSize(textsize); + + SetAttText((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -1567,17 +1558,27 @@ void TGWin32::SetTextSize(Float_t textsize) void TGWin32::ClearWindow() { - if (!fWindows) return; + ClearWindowW((WinContext_t) gCws); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Clear specified window. - if (!gCws->ispixmap && !gCws->double_buffer) { - gdk_window_set_background(gCws->drawing, (GdkColor *) & GetColor(0).color); - gdk_window_clear(gCws->drawing); +void TGWin32::ClearWindowW(WinContext_t wctxt) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; + + if (!ctxt->ispixmap && !ctxt->double_buffer) { + gdk_window_set_background(ctxt->drawing, (GdkColor *) & GetColor(0).color); + gdk_window_clear(ctxt->drawing); GdiFlush(); } else { - SetColor(gGCpxmp, 0); - gdk_win32_draw_rectangle(gCws->drawing, gGCpxmp, 1, - 0, 0, gCws->width, gCws->height); - SetColor(gGCpxmp, 1); + SetColor(ctxt, ctxt->fGClist[kGCpxmp], 0); + gdk_win32_draw_rectangle(ctxt->drawing, ctxt->fGClist[kGCpxmp], 1, + 0, 0, ctxt->width, ctxt->height); + SetColor(ctxt, ctxt->fGClist[kGCpxmp], 1); } } @@ -1586,7 +1587,7 @@ void TGWin32::ClearWindow() void TGWin32::ClosePixmap() { - CloseWindow1(); + CloseWindow(); } //////////////////////////////////////////////////////////////////////////////// @@ -1594,20 +1595,17 @@ void TGWin32::ClosePixmap() void TGWin32::CloseWindow() { - CloseWindow1(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Delete current window. - -void TGWin32::CloseWindow1() -{ - int wid; + if (!gCws->shared) { + if (gCws->ispixmap) { + gdk_pixmap_unref(gCws->window); + } else { + gdk_window_destroy(gCws->window, kTRUE); + } + } - if (gCws->ispixmap) { - gdk_pixmap_unref(gCws->window); - } else { - gdk_window_destroy(gCws->window, kTRUE); + if (gCws->fillPattern) { + gdk_pixmap_unref(gCws->fillPattern); + gCws->fillPattern = nullptr; } if (gCws->buffer) { @@ -1618,22 +1616,31 @@ void TGWin32::CloseWindow1() (GdkColor *)gCws->new_colors, gCws->ncolors); delete [] gCws->new_colors; - gCws->new_colors = 0; + gCws->new_colors = nullptr; } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_unref(gCws->fGClist[i]); // gdk_gc_unref is equivalent to gdk_gc_destroy + GdiFlush(); gCws->open = 0; - if (!fWindows) return; + for (auto iter = fWindows.begin(); iter != fWindows.end(); ++iter) + if (iter->second.get() == gCws) { + fWindows.erase(iter); + gCws = nullptr; + break; + } + + if (gCws) + Fatal("CloseWindow", "Not found gCws in list of windows"); // make first window in list the current window - for (wid = 0; wid < fMaxNumberOfWindows; wid++) { - if (fWindows[wid].open) { - gCws = &fWindows[wid]; + for (auto iter = fWindows.begin(); iter != fWindows.end(); ++iter) + if (iter->second && iter->second->open) { + gCws = iter->second.get(); return; } - } - gCws = 0; } //////////////////////////////////////////////////////////////////////////////// @@ -1641,10 +1648,11 @@ void TGWin32::CloseWindow1() void TGWin32::CopyPixmap(int wid, int xpos, int ypos) { - if (!fWindows) return; + if (fWindows.count(wid) == 0) + return; - gTws = &fWindows[wid]; - gdk_window_copy_area(gCws->drawing, gGCpxmp, xpos, ypos, gTws->drawing, + gTws = fWindows[wid].get(); + gdk_window_copy_area(gCws->drawing, gTws->fGClist[kGCpxmp], xpos, ypos, gTws->drawing, 0, 0, gTws->width, gTws->height); GdiFlush(); } @@ -1656,7 +1664,19 @@ void TGWin32::CopyPixmap(int wid, int xpos, int ypos) void TGWin32::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode) { - if (!fWindows) return; + DrawBoxW((WinContext_t) gCws, x1, y1, x2, y2, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw a box on specified window. +/// mode=0 hollow (kHollow) +/// mode=1 solid (kSolid) + +void TGWin32::DrawBoxW(WinContext_t wctxt, int x1, int y1, int x2, int y2, EBoxMode mode) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; Int_t x = TMath::Min(x1, x2); Int_t y = TMath::Min(y1, y2); @@ -1664,21 +1684,16 @@ void TGWin32::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode) Int_t h = TMath::Abs(y2 - y1); switch (mode) { + case kHollow: + gdk_win32_draw_rectangle(ctxt->drawing, ctxt->fGClist[kGCline], 0, x, y, w, h); + break; - case kHollow: - if (fLineColorModified) UpdateLineColor(); - if (fPenModified) UpdateLineStyle(); - gdk_win32_draw_rectangle(gCws->drawing, gGCline, 0, x, y, w, h); - break; - - case kFilled: - if (fFillStyleModified) UpdateFillStyle(); - if (fFillColorModified) UpdateFillColor(); - gdk_win32_draw_rectangle(gCws->drawing, gGCfill, 1, x, y, w, h); - break; + case kFilled: + gdk_win32_draw_rectangle(ctxt->drawing, ctxt->fGClist[kGCfill], 1, x, y, w, h); + break; - default: - break; + default: + break; } } @@ -1696,28 +1711,23 @@ void TGWin32::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode) void TGWin32::DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx, Int_t ny, Int_t *ic) { - int i, j, icol, ix, iy, w, h, current_icol; - - if (!fWindows) return; - - current_icol = -1; - w = TMath::Max((x2 - x1) / (nx), 1); - h = TMath::Max((y1 - y2) / (ny), 1); - ix = x1; + if (!gCws) return; - if (fFillStyleModified) UpdateFillStyle(); - if (fFillColorModified) UpdateFillColor(); + int current_icol = -1; + int w = TMath::Max((x2 - x1) / (nx), 1); + int h = TMath::Max((y1 - y2) / (ny), 1); + int ix = x1; - for (i = 0; i < nx; i++) { - iy = y1 - h; - for (j = 0; j < ny; j++) { - icol = ic[i + (nx * j)]; + for (int i = 0; i < nx; i++) { + int iy = y1 - h; + for (int j = 0; j < ny; j++) { + int icol = ic[i + (nx * j)]; if (icol != current_icol) { - gdk_gc_set_foreground(gGCfill, (GdkColor *) & GetColor(icol).color); + gdk_gc_set_foreground(gCws->fGClist[kGCfill], (GdkColor *) & GetColor(icol).color); current_icol = icol; } - gdk_win32_draw_rectangle(gCws->drawing, gGCfill, kTRUE, ix, iy, w, h); + gdk_win32_draw_rectangle(gCws->drawing, gCws->fGClist[kGCfill], kTRUE, ix, iy, w, h); iy = iy - h; } ix = ix + w; @@ -1731,29 +1741,30 @@ void TGWin32::DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, void TGWin32::DrawFillArea(int n, TPoint *xyt) { - int i; - static int lastn = 0; - static GdkPoint *xy = 0; + DrawFillAreaW((WinContext_t) gCws, n, xyt); +} - if (!fWindows) return; +//////////////////////////////////////////////////////////////////////////////// +/// Fill area described by polygon in a specified window. +/// n : number of points +/// xy(2,n) : list of points - if (fFillStyleModified) UpdateFillStyle(); - if (fFillColorModified) UpdateFillColor(); +void TGWin32::DrawFillAreaW(WinContext_t wctxt, int n, TPoint *xyt) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - if (lastn!=n) { - delete [] (GdkPoint *)xy; - xy = new GdkPoint[n]; - lastn = n; - } - for (i = 0; i < n; i++) { + std::vector xy(n); + for (int i = 0; i < n; i++) { xy[i].x = xyt[i].fX; xy[i].y = xyt[i].fY; } - if (gFillHollow) { - gdk_win32_draw_lines(gCws->drawing, gGCfill, xy, n); + if (ctxt->fillHollow) { + gdk_win32_draw_lines(ctxt->drawing, ctxt->fGClist[kGCfill], xy.data(), n); } else { - gdk_win32_draw_polygon(gCws->drawing, gGCfill, 1, xy, n); + gdk_win32_draw_polygon(ctxt->drawing, ctxt->fGClist[kGCfill], 1, xy.data(), n); } } @@ -1764,24 +1775,25 @@ void TGWin32::DrawFillArea(int n, TPoint *xyt) void TGWin32::DrawLine(Int_t x1, Int_t y1, Int_t x2, Int_t y2) { - if (!fWindows) return; + DrawLineW((WinContext_t) gCws, x1, y1, x2, y2); +} - if (fLineColorModified) UpdateLineColor(); - if (fPenModified) UpdateLineStyle(); +//////////////////////////////////////////////////////////////////////////////// +/// Draw a line on specified window. +/// x1,y1 : begin of line +/// x2,y2 : end of line + +void TGWin32::DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - if (gLineStyle == GDK_LINE_SOLID) { - gdk_draw_line(gCws->drawing, gGCline, x1, y1, x2, y2); + if (ctxt->lineStyle == GDK_LINE_SOLID) { + gdk_draw_line(ctxt->drawing, ctxt->fGClist[kGCline], x1, y1, x2, y2); } else { - int i; - gint8 dashes[32]; - for (i = 0; i < gDashSize; i++) { - dashes[i] = (gint8) gDashList[i]; - } - for (i = gDashSize; i < 32; i++) { - dashes[i] = (gint8) 0; - } - gdk_gc_set_dashes(gGCdash, gDashOffset, dashes, gDashSize); - gdk_draw_line(gCws->drawing, gGCdash, x1, y1, x2, y2); + gdk_gc_set_dashes(ctxt->fGClist[kGCdash], ctxt->dashOffset, ctxt->dashList.data(), ctxt->dashList.size()); + gdk_draw_line(ctxt->drawing, ctxt->fGClist[kGCdash], x1, y1, x2, y2); } } @@ -1792,55 +1804,63 @@ void TGWin32::DrawLine(Int_t x1, Int_t y1, Int_t x2, Int_t y2) void TGWin32::DrawPolyLine(int n, TPoint * xyt) { - int i; + DrawPolyLineW((WinContext_t) gCws, n, xyt); +} - if (!fWindows) return; +//////////////////////////////////////////////////////////////////////////////// +/// Draw a line through all points in specified window. +/// n : number of points +/// xy : list of points - Point_t *xy = new Point_t[n]; +void TGWin32::DrawPolyLineW(WinContext_t wctxt, int n, TPoint * xyt) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt || (n < 1)) + return; - for (i = 0; i < n; i++) { - xy[i].fX = xyt[i].fX; - xy[i].fY = xyt[i].fY; + std::vector xy(n); + for (int i = 0; i < n; i++) { + xy[i].x = xyt[i].fX; + xy[i].y = xyt[i].fY; } - if (fLineColorModified) UpdateLineColor(); - if (fPenModified) UpdateLineStyle(); - if (n > 1) { - if (gLineStyle == GDK_LINE_SOLID) { - gdk_win32_draw_lines(gCws->drawing, gGCline, (GdkPoint *)xy, n); + if (ctxt->lineStyle == GDK_LINE_SOLID) { + gdk_win32_draw_lines(ctxt->drawing, ctxt->fGClist[kGCline], xy.data(), n); } else { - int i; - gint8 dashes[32]; - - for (i = 0; i < gDashSize; i++) { - dashes[i] = (gint8) gDashList[i]; - } - for (i = gDashSize; i < 32; i++) { - dashes[i] = (gint8) 0; - } - - gdk_gc_set_dashes(gGCdash, gDashOffset, dashes, gDashSize); - gdk_win32_draw_lines(gCws->drawing, (GdkGC*)gGCdash, (GdkPoint *)xy, n); + gdk_gc_set_dashes(ctxt->fGClist[kGCdash], ctxt->dashOffset, ctxt->dashList.data(), ctxt->dashList.size()); + gdk_win32_draw_lines(ctxt->drawing, ctxt->fGClist[kGCdash], xy.data(), n); // calculate length of line to update dash offset - for (i = 1; i < n; i++) { - int dx = xy[i].fX - xy[i - 1].fX; - int dy = xy[i].fY - xy[i - 1].fY; + for (int i = 1; i < n; i++) { + int dx = xy[i].x - xy[i - 1].x; + int dy = xy[i].y - xy[i - 1].y; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; - gDashOffset += dx > dy ? dx : dy; + ctxt->dashOffset += dx > dy ? dx : dy; } - gDashOffset %= gDashLength; + ctxt->dashOffset %= ctxt->dashLength; } } else { - gdk_win32_draw_points( gCws->drawing, gLineStyle == GDK_LINE_SOLID ? - gGCline : gGCdash, (GdkPoint *)xy,1); + gdk_win32_draw_points(ctxt->drawing, + ctxt->fGClist[ctxt->lineStyle == GDK_LINE_SOLID ? kGCline : kGCdash], + xy.data(), 1); } - delete [] xy; } +//////////////////////////////////////////////////////////////////////////////// +/// Draw N segments on specified window +/// n : number of segments +/// xy : list of points, 2*N size + +void TGWin32::DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xyt) +{ + for(Int_t i = 0; i < 2*n; i += 2) + DrawPolyLineW(wctxt, 2, &xyt[i]); +} + + //////////////////////////////////////////////////////////////////////////////// /// Draw n markers with the current attributes at position x, y. /// n : number of markers to draw @@ -1848,72 +1868,69 @@ void TGWin32::DrawPolyLine(int n, TPoint * xyt) void TGWin32::DrawPolyMarker(int n, TPoint *xyt) { - int i; - static int lastn = 0; - static GdkPoint *xy = 0; - - if (!fWindows) return; + DrawPolyMarkerW((WinContext_t) gCws, n, xyt); +} - if (fMarkerStyleModified) UpdateMarkerStyle(); - if (fMarkerColorModified) UpdateMarkerColor(); +//////////////////////////////////////////////////////////////////////////////// +/// Draw n markers with the current attributes at position x, y in specified window. +/// n : number of markers to draw +/// xy : x,y coordinates of markers - if (lastn!=n) { - delete [] (GdkPoint *)xy; - xy = new GdkPoint[n]; - lastn = n; - } +void TGWin32::DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xyt) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) return; - for (i = 0; i < n; i++) { - xy[i].x = xyt[i].fX; - xy[i].y = xyt[i].fY; - } + if ((ctxt->markerShape.size() == 0) && (ctxt->markerSize <= 0)) { + std::vector xy(n); + for (int i = 0; i < n; i++) { + xy[i].x = xyt[i].fX; + xy[i].y = xyt[i].fY; + } - if (gMarker.n <= 0) { - gdk_win32_draw_points(gCws->drawing, gGCmark, xy, n); + gdk_win32_draw_points(ctxt->drawing, ctxt->fGClist[kGCmark], xy.data(), n); } else { - int r = gMarker.n / 2; - int m; + int r = ctxt->markerSize / 2; + auto &shape = ctxt->markerShape; - for (m = 0; m < n; m++) { + for (int m = 0; m < n; m++) { int hollow = 0; - switch (gMarker.type) { - int i; - + switch (ctxt->markerType) { case 0: // hollow circle - gdk_win32_draw_arc(gCws->drawing, gGCmark, kFALSE, xy[m].x-r, xy[m].y-r, - gMarker.n, gMarker.n, 0, 23040); + gdk_win32_draw_arc(ctxt->drawing, ctxt->fGClist[kGCmark], kFALSE, xyt[m].fX - r, xyt[m].fY - r, + ctxt->markerSize, ctxt->markerSize, 0, 23040); break; case 1: // filled circle - gdk_win32_draw_arc(gCws->drawing, gGCmark, kTRUE, xy[m].x-r, xy[m].y-r, - gMarker.n, gMarker.n, 0, 23040); + gdk_win32_draw_arc(ctxt->drawing, ctxt->fGClist[kGCmark], kTRUE, xyt[m].fX - r, xyt[m].fY - r, + ctxt->markerSize, ctxt->markerSize, 0, 23040); break; case 2: // hollow polygon hollow = 1; case 3: // filled polygon - for (i = 0; i < gMarker.n; i++) { - gMarker.xy[i].x += xy[m].x; - gMarker.xy[i].y += xy[m].y; + for (size_t i = 0; i < shape.size(); i++) { + shape[i].x += xyt[m].fX; + shape[i].y += xyt[m].fY; } if (hollow) { - gdk_win32_draw_lines(gCws->drawing, gGCmark, (GdkPoint *)gMarker.xy, gMarker.n); + gdk_win32_draw_lines(ctxt->drawing, ctxt->fGClist[kGCmark], shape.data(), shape.size()); } else { - gdk_win32_draw_polygon(gCws->drawing, gGCmark, 1, (GdkPoint *)gMarker.xy, gMarker.n); + gdk_win32_draw_polygon(ctxt->drawing, ctxt->fGClist[kGCmark], 1, shape.data(), shape.size()); } - for (i = 0; i < gMarker.n; i++) { - gMarker.xy[i].x -= xy[m].x; - gMarker.xy[i].y -= xy[m].y; + for (size_t i = 0; i < shape.size(); i++) { + shape[i].x -= xyt[m].fX; + shape[i].y -= xyt[m].fY; } break; - case 4: // segmented line - for (i = 0; i < gMarker.n; i += 2) { - gdk_draw_line(gCws->drawing, gGCmark, - xy[m].x + gMarker.xy[i].x, - xy[m].y + gMarker.xy[i].y, - xy[m].x + gMarker.xy[i + 1].x, - xy[m].y + gMarker.xy[i + 1].y); + case 4: // segmented line + for (size_t i = 0; i < shape.size(); i += 2) { + gdk_draw_line(ctxt->drawing, ctxt->fGClist[kGCmark], + xyt[m].fX + shape[i].x, + xyt[m].fY + shape[i].y, + xyt[m].fX + shape[i+1].x, + xyt[m].fY + shape[i+1].y); } break; } @@ -1963,7 +1980,11 @@ GdkGC *TGWin32::GetGC(Int_t which) const return 0; } - return gGClist[which]; + if (!gCws) { + Error("GetGC", "No current window selected"); + return nullptr; + } + return gCws->fGClist[which]; } //////////////////////////////////////////////////////////////////////////////// @@ -1971,9 +1992,10 @@ GdkGC *TGWin32::GetGC(Int_t which) const Int_t TGWin32::GetDoubleBuffer(int wid) { - if (!fWindows) return 0; + if (fWindows.count(wid) == 0) + return 0; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); if (!gTws->open) { return -1; @@ -1992,8 +2014,6 @@ Int_t TGWin32::GetDoubleBuffer(int wid) void TGWin32::GetGeometry(int wid, int &x, int &y, unsigned int &w, unsigned int &h) { - if (!fWindows) return; - if (wid < 0) { x = 0; y = 0; @@ -2004,7 +2024,9 @@ void TGWin32::GetGeometry(int wid, int &x, int &y, unsigned int &w, int depth; int width, height; - gTws = &fWindows[wid]; + if (fWindows.count(wid) == 0) return; + + gTws = fWindows[wid].get(); gdk_window_get_geometry((GdkDrawable *) gTws->window, &x, &y, &width, &height, &depth); @@ -2071,8 +2093,8 @@ void TGWin32::GetTextExtent(UInt_t &w, UInt_t &h, char *mess) Window_t TGWin32::GetWindowID(int wid) { - if (!fWindows) return 0; - return (Window_t) fWindows[wid].window; + if (fWindows.count(wid) == 0) return 0; + return (Window_t) fWindows[wid]->window; } //////////////////////////////////////////////////////////////////////////////// @@ -2083,14 +2105,65 @@ Window_t TGWin32::GetWindowID(int wid) void TGWin32::MoveWindow(Int_t wid, Int_t x, Int_t y) { - if (!fWindows) return; + if (fWindows.count(wid) == 0) return; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); if (!gTws->open) return; + // prevent hiding the titlebar + if (x == 0 && y == 0) { + x = 1; y = 1; + } gdk_window_move((GdkDrawable *) gTws->window, x, y); } +//////////////////////////////////////////////////////////////////////////////// +/// Add new window handle +/// Only for private usage + +Int_t TGWin32::AddWindowHandle() +{ + Int_t maxid = 0; + for (auto & pair : fWindows) { + if (pair.first > maxid) + maxid = pair.first; + } + + if (fWindows.size() == (size_t) maxid) { + // all ids are in use - just add maximal+1 + maxid++; + } else + for (int id = 1; id < maxid; id++) { + if (fWindows.count(id) == 0) { + maxid = id; + break; + } + } + + fWindows.emplace(maxid, std::make_unique()); + + auto ctxt = fWindows[maxid].get(); + ctxt->open = 1; + ctxt->shared = 0; + ctxt->drawing = nullptr; + ctxt->window = nullptr; + ctxt->buffer = nullptr; + ctxt->new_colors = nullptr; + ctxt->ncolors = 0; + + ctxt->drawMode = TVirtualX::kCopy; + + // Create primitives graphic contexts + for (int i = 0; i < kMAXGC; i++) { + ctxt->fGClist[i] = gdk_gc_new(GDK_ROOT_PARENT()); + gdk_gc_set_foreground(ctxt->fGClist[i], &GetColor(1).color); + gdk_gc_set_background(ctxt->fGClist[i], &GetColor(0).color); + } + + return maxid; +} + + //////////////////////////////////////////////////////////////////////////////// /// Open a new pixmap. /// w,h : Width and height of the pixmap. @@ -2098,54 +2171,33 @@ void TGWin32::MoveWindow(Int_t wid, Int_t x, Int_t y) Int_t TGWin32::OpenPixmap(unsigned int w, unsigned int h) { int wval, hval; - int i, wid; int ww, hh, depth; wval = w; hval = h; - // Select next free window number - again: - for (wid = 0; wid < fMaxNumberOfWindows; wid++) { - if (!fWindows[wid].open) { - fWindows[wid].open = 1; - gCws = &fWindows[wid]; - break; - } - } - if (wid == fMaxNumberOfWindows) { - int newsize = fMaxNumberOfWindows + 10; - fWindows = (XWindow_t *) TStorage::ReAlloc(fWindows, - newsize * sizeof(XWindow_t), - fMaxNumberOfWindows * - sizeof(XWindow_t)); + int wid = AddWindowHandle(); - for (i = fMaxNumberOfWindows; i < newsize; i++) fWindows[i].open = 0; - fMaxNumberOfWindows = newsize; - goto again; - } + gCws = fWindows[wid].get(); + gCws->ispixmap = 1; - depth =gdk_visual_get_best_depth(); + depth = gdk_visual_get_best_depth(); gCws->window = (GdkPixmap *) gdk_pixmap_new(GDK_ROOT_PARENT(),wval,hval,depth); gdk_drawable_get_size((GdkDrawable *) gCws->window, &ww, &hh); - for (i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gCws->fGClist[i], (GdkDrawable *)None); - SetColor(gGCpxmp, 0); - gdk_win32_draw_rectangle(gCws->window,(GdkGC *)gGCpxmp, kTRUE, + SetColor(gCws, gCws->fGClist[kGCpxmp], 0); + gdk_win32_draw_rectangle(gCws->window, gCws->fGClist[kGCpxmp], kTRUE, 0, 0, ww, hh); - SetColor(gGCpxmp, 1); + SetColor(gCws, gCws->fGClist[kGCpxmp], 1); // Initialise the window structure gCws->drawing = gCws->window; - gCws->buffer = 0; gCws->double_buffer = 0; - gCws->ispixmap = 1; gCws->clip = 0; gCws->width = wval; gCws->height = hval; - gCws->new_colors = 0; return wid; } @@ -2158,41 +2210,18 @@ Int_t TGWin32::InitWindow(ULongptr_t win) { GdkWindowAttr attributes; unsigned long attr_mask = 0; - int wid; int xval, yval; int wval, hval, depth; - GdkWindow *wind = (GdkWindow *) win; - - gdk_window_get_geometry(wind, &xval, &yval, &wval, &hval, &depth); - - // Select next free window number + int wid = AddWindowHandle(); - again: - for (wid = 0; wid < fMaxNumberOfWindows; wid++) { - if (!fWindows[wid].open) { - fWindows[wid].open = 1; - fWindows[wid].double_buffer = 0; - gCws = &fWindows[wid]; - break; - } - } + gCws = fWindows[wid].get(); + gCws->ispixmap = 0; - if (wid == fMaxNumberOfWindows) { - int newsize = fMaxNumberOfWindows + 10; - fWindows = - (XWindow_t *) TStorage::ReAlloc(fWindows, - newsize * sizeof(XWindow_t), - fMaxNumberOfWindows * - sizeof(XWindow_t)); + GdkWindow *wind = (GdkWindow *) win; - for (int i = fMaxNumberOfWindows; i < newsize; i++) { - fWindows[i].open = 0; - } + gdk_window_get_geometry(wind, &xval, &yval, &wval, &hval, &depth); - fMaxNumberOfWindows = newsize; - goto again; - } // Create window attributes.wclass = GDK_INPUT_OUTPUT; attributes.event_mask = 0L; //GDK_ALL_EVENTS_MASK; @@ -2241,13 +2270,10 @@ Int_t TGWin32::InitWindow(ULongptr_t win) // Initialise the window structure gCws->drawing = gCws->window; - gCws->buffer = 0; gCws->double_buffer = 0; - gCws->ispixmap = 0; gCws->clip = 0; gCws->width = wval; gCws->height = hval; - gCws->new_colors = 0; return wid; } @@ -2696,11 +2722,9 @@ Int_t TGWin32::RequestString(int x, int y, char *text) void TGWin32::RescaleWindow(int wid, unsigned int w, unsigned int h) { - int i; - - if (!fWindows) return; + if (fWindows.count(wid) == 0) return; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); if (!gTws->open) return; @@ -2717,14 +2741,14 @@ void TGWin32::RescaleWindow(int wid, unsigned int w, unsigned int h) gTws->buffer = gdk_pixmap_new(GDK_ROOT_PARENT(), // NULL, w, h, gdk_visual_get_best_depth()); } - for (i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask(gGClist[i], (GdkBitmap *)None); - } - SetColor(gGCpxmp, 0); - gdk_win32_draw_rectangle(gTws->buffer, gGCpxmp, 1, 0, 0, w, h); - SetColor(gGCpxmp, 1); + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gTws->fGClist[i], (GdkBitmap *)None); + SetColor(gTws, gTws->fGClist[kGCpxmp], 0); + gdk_win32_draw_rectangle(gTws->buffer, gTws->fGClist[kGCpxmp], 1, 0, 0, w, h); + SetColor(gTws, gTws->fGClist[kGCpxmp], 1); - if (gTws->double_buffer) gTws->drawing = gTws->buffer; + if (gTws->double_buffer) + gTws->drawing = gTws->buffer; } gTws->width = w; gTws->height = h; @@ -2738,14 +2762,13 @@ void TGWin32::RescaleWindow(int wid, unsigned int w, unsigned int h) int TGWin32::ResizePixmap(int wid, unsigned int w, unsigned int h) { int wval, hval; - int i; int ww, hh, depth; wval = w; hval = h; - if (!fWindows) return 0; + if (fWindows.count(wid) == 0) return 0; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); // don't do anything when size did not change // if (gTws->width == wval && gTws->height == hval) return 0; @@ -2765,13 +2788,12 @@ int TGWin32::ResizePixmap(int wid, unsigned int w, unsigned int h) gdk_drawable_get_size(gTws->window, &ww, &hh); - for (i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gTws->fGClist[i], (GdkDrawable *)None); - SetColor(gGCpxmp, 0); - gdk_win32_draw_rectangle(gTws->window,(GdkGC *)gGCpxmp, kTRUE, 0, 0, ww, hh); - SetColor(gGCpxmp, 1); + SetColor(gTws, gTws->fGClist[kGCpxmp], 0); + gdk_win32_draw_rectangle(gTws->window, gTws->fGClist[kGCpxmp], kTRUE, 0, 0, ww, hh); + SetColor(gTws, gTws->fGClist[kGCpxmp], 1); // Initialise the window structure gTws->drawing = gTws->window; @@ -2785,16 +2807,13 @@ int TGWin32::ResizePixmap(int wid, unsigned int w, unsigned int h) void TGWin32::ResizeWindow(Int_t wid) { - int i; - int xval = 0, yval = 0; - GdkWindow *win, *root = NULL; - int wval = 0, hval = 0, depth = 0; + if (fWindows.count(wid) == 0) return; - if (!fWindows) return; + int xval = 0, yval = 0, wval = 0, hval = 0, depth = 0; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); - win = (GdkWindow *) gTws->window; + auto win = (GdkWindow *) gTws->window; gdk_window_get_geometry(win, &xval, &yval, &wval, &hval, &depth); @@ -2813,16 +2832,16 @@ void TGWin32::ResizeWindow(Int_t wid) wval, hval, depth); } - for (i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gTws->fGClist[i], (GdkDrawable *)None); - SetColor(gGCpxmp, 0); - gdk_win32_draw_rectangle(gTws->buffer,(GdkGC *)gGCpxmp, kTRUE, 0, 0, wval, hval); + SetColor(gTws, gTws->fGClist[kGCpxmp], 0); + gdk_win32_draw_rectangle(gTws->buffer, gTws->fGClist[kGCpxmp], kTRUE, 0, 0, wval, hval); - SetColor(gGCpxmp, 1); + SetColor(gTws, gTws->fGClist[kGCpxmp], 1); - if (gTws->double_buffer) gTws->drawing = gTws->buffer; + if (gTws->double_buffer) + gTws->drawing = gTws->buffer; } gTws->width = wval; @@ -2834,28 +2853,24 @@ void TGWin32::ResizeWindow(Int_t wid) void TGWin32::SelectWindow(int wid) { - int i; - GdkRectangle rect; + if (fWindows.count(wid) == 0) return; - if (!fWindows || wid < 0 || wid >= fMaxNumberOfWindows || !fWindows[wid].open) { - return; - } + if (!fWindows[wid]->open) return; - gCws = &fWindows[wid]; + gCws = fWindows[wid].get(); if (gCws->clip && !gCws->ispixmap && !gCws->double_buffer) { + GdkRectangle rect; rect.x = gCws->xclip; rect.y = gCws->yclip; rect.width = gCws->wclip; rect.height = gCws->hclip; - for (i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_rectangle((GdkGC *) gGClist[i], &rect); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_rectangle(gCws->fGClist[i], &rect); } else { - for (i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gCws->fGClist[i], (GdkDrawable *)None); } } @@ -2893,14 +2908,13 @@ void TGWin32::SetCharacterUp(Float_t chupx, Float_t chupy) void TGWin32::SetClipOFF(int wid) { - if (!fWindows) return; + if (fWindows.count(wid) == 0) return; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); gTws->clip = 0; - for (int i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gTws->fGClist[i], (GdkDrawable *)None); } //////////////////////////////////////////////////////////////////////////////// @@ -2912,25 +2926,24 @@ void TGWin32::SetClipOFF(int wid) void TGWin32::SetClipRegion(int wid, int x, int y, unsigned int w, unsigned int h) { - if (!fWindows) return; + if (fWindows.count(wid) == 0) return; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); gTws->xclip = x; gTws->yclip = y; gTws->wclip = w; gTws->hclip = h; gTws->clip = 1; - GdkRectangle rect; if (gTws->clip && !gTws->ispixmap && !gTws->double_buffer) { + GdkRectangle rect; rect.x = gTws->xclip; rect.y = gTws->yclip; rect.width = gTws->wclip; rect.height = gTws->hclip; - for (int i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_rectangle((GdkGC *)gGClist[i], &rect); - } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_rectangle(gTws->fGClist[i], &rect); } } @@ -2949,12 +2962,12 @@ ULong_t TGWin32::GetPixel(Color_t ci) //////////////////////////////////////////////////////////////////////////////// /// Set the foreground color in GdkGC. -void TGWin32::SetColor(GdkGC *gc, int ci) +void TGWin32::SetColor(XWindow_t *ctxt, GdkGC *gc, int ci) { GdkGCValues gcvals; GdkColor color; - if (ci<=0) ci = 10; //white + if (ci <= 0) ci = 10; //white TColor *clr = gROOT->GetColor(ci); if (clr) @@ -2967,7 +2980,7 @@ void TGWin32::SetColor(GdkGC *gc, int ci) col = GetColor(0); } - if (fDrawMode == kXor) { + if (ctxt && ctxt->drawMode == kXor) { gdk_gc_get_values(gc, &gcvals); color.pixel = col.color.pixel ^ gcvals.background.pixel; @@ -2993,9 +3006,9 @@ void TGWin32::SetColor(GdkGC *gc, int ci) void TGWin32::SetCursor(Int_t wid, ECursor cursor) { - if (!fWindows) return; + if (fWindows.count(wid) == 0) return; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); gdk_window_set_cursor((GdkWindow *)gTws->window, (GdkCursor *)fCursors[cursor]); } @@ -3025,11 +3038,9 @@ void TGWin32::SetCursor(Window_t id, Cursor_t curid) void TGWin32::SetDoubleBuffer(int wid, int mode) { - if (!fWindows) return; - if (wid == 999) { - for (int i = 0; i < fMaxNumberOfWindows; i++) { - gTws = &fWindows[i]; + for (auto & pair : fWindows) { + gTws = pair.second.get(); if (gTws->open) { switch (mode) { case 1: @@ -3042,7 +3053,9 @@ void TGWin32::SetDoubleBuffer(int wid, int mode) } } } else { - gTws = &fWindows[wid]; + if (fWindows.count(wid) == 0) return; + + gTws = fWindows[wid].get(); if (!gTws->open) return; switch (mode) { @@ -3071,20 +3084,19 @@ void TGWin32::SetDoubleBufferOFF() void TGWin32::SetDoubleBufferON() { - if (!fWindows || gTws->double_buffer || gTws->ispixmap) return; + if (fWindows.size() == 0 || !gTws || gTws->double_buffer || gTws->ispixmap) return; if (!gTws->buffer) { gTws->buffer = gdk_pixmap_new(GDK_ROOT_PARENT(), //NULL, gTws->width, gTws->height, gdk_visual_get_best_depth()); - SetColor(gGCpxmp, 0); - gdk_win32_draw_rectangle(gTws->buffer, gGCpxmp, 1, 0, 0, gTws->width, - gTws->height); - SetColor(gGCpxmp, 1); - } - for (int i = 0; i < kMAXGC; i++) { - gdk_gc_set_clip_mask(gGClist[i], (GdkBitmap *)None); + SetColor(gTws, gTws->fGClist[kGCpxmp], 0); + gdk_win32_draw_rectangle(gTws->buffer, gTws->fGClist[kGCpxmp], 1, 0, 0, + gTws->width, gTws->height); + SetColor(gTws, gTws->fGClist[kGCpxmp], 1); } + for (int i = 0; i < kMAXGC; i++) + gdk_gc_set_clip_mask(gTws->fGClist[i], (GdkBitmap *)None); gTws->double_buffer = 1; gTws->drawing = gTws->buffer; } @@ -3100,29 +3112,7 @@ void TGWin32::SetDoubleBufferON() void TGWin32::SetDrawMode(EDrawMode mode) { - int i; - - switch (mode) { - case kCopy: - for (i = 0; i < kMAXGC; i++) { - if (gGClist[i]) - gdk_gc_set_function(gGClist[i], GDK_COPY); - } - break; - case kXor: - for (i = 0; i < kMAXGC; i++) { - if (gGClist[i]) - gdk_gc_set_function(gGClist[i], GDK_XOR); - } - break; - case kInvert: - for (i = 0; i < kMAXGC; i++) { - if (gGClist[i]) - gdk_gc_set_function(gGClist[i], GDK_INVERT); - } - break; - } - fDrawMode = mode; + SetDrawModeW((WinContext_t) gCws, mode); } //////////////////////////////////////////////////////////////////////////////// @@ -3130,31 +3120,14 @@ void TGWin32::SetDrawMode(EDrawMode mode) void TGWin32::SetFillColor(Color_t cindex) { - Int_t indx = Int_t(cindex); + if (cindex < 0) return; - if (!gStyle->GetFillColor() && cindex > 1) { - indx = 0; - } + TAttFill::SetFillColor(cindex); - fFillColor = indx; - fFillColorModified = kTRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -/// + TAttFill arg(gCws->fAttFill); + arg.SetFillColor(cindex); -void TGWin32::UpdateFillColor() -{ - if (fFillColor >= 0) { - SetColor(gGCfill, fFillColor); - } - - // invalidate fill pattern - if (gFillPattern != NULL) { - gdk_pixmap_unref(gFillPattern); - gFillPattern = NULL; - } - fFillColorModified = kFALSE; + SetAttFill((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -3164,58 +3137,77 @@ void TGWin32::UpdateFillColor() void TGWin32::SetFillStyle(Style_t fstyle) { - if (fFillStyle==fstyle) return; + TAttFill::SetFillStyle(fstyle); - fFillStyle = fstyle; - fFillStyleModified = kTRUE; + TAttFill arg(gCws->fAttFill); + arg.SetFillStyle(fstyle); + + SetAttFill((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// Set fill area style index. +/// Return current fill style +/// FIXME: Only as temporary solution while some code analyze current fill style -void TGWin32::UpdateFillStyle() +Style_t TGWin32::GetFillStyle() const { - static int current_fasi = 0; + return gCws ? gCws->fAttFill.GetFillStyle() : TAttFill::GetFillStyle(); +} - Int_t style = fFillStyle / 1000; - Int_t fasi = fFillStyle % 1000; +//////////////////////////////////////////////////////////////////////////////// +/// Set fill attributes for specified window - switch (style) { +void TGWin32::SetAttFill(WinContext_t wctxt, const TAttFill &att) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - case 1: // solid - gFillHollow = 0; - gdk_gc_set_fill(gGCfill, GDK_SOLID); - break; + Int_t cindex = att.GetFillColor(); + if (!gStyle->GetFillColor() && cindex > 1) + cindex = 0; + if (cindex >= 0) + SetColor(ctxt, ctxt->fGClist[kGCfill], Int_t(cindex)); + ctxt->fAttFill.SetFillColor(cindex); - case 2: // pattern - gFillHollow = 1; - break; + Int_t style = att.GetFillStyle() / 1000; + Int_t fasi = att.GetFillStyle() % 1000; - case 3: // hatch - gFillHollow = 0; - gdk_gc_set_fill(gGCfill, GDK_STIPPLED); + switch (style) { + case 1: // solid + ctxt->fillHollow = 0; + gdk_gc_set_fill(ctxt->fGClist[kGCfill], GDK_SOLID); + break; - if (fasi != current_fasi) { - if (gFillPattern != NULL) { - gdk_pixmap_unref(gFillPattern); - gFillPattern = NULL; + case 2: // pattern + ctxt->fillHollow = 1; + break; + + case 3: // hatch + ctxt->fillHollow = 0; + gdk_gc_set_fill(ctxt->fGClist[kGCfill], GDK_STIPPLED); + + if (fasi != ctxt->fillFasi) { + if (ctxt->fillPattern) { + gdk_pixmap_unref(ctxt->fillPattern); + ctxt->fillPattern = nullptr; + } + int stn = (fasi >= 1 && fasi <=25) ? fasi : 2; + char pattern[32]; + for (int i = 0; i < 32; ++i) + pattern[i] = ~gStipples[stn][i]; + ctxt->fillPattern = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(), + (const char *)&pattern, 16, 16); + gdk_gc_set_stipple(ctxt->fGClist[kGCfill], ctxt->fillPattern); + ctxt->fillFasi = fasi; } - int stn = (fasi >= 1 && fasi <=25) ? fasi : 2; - char pattern[32]; - for (int i=0;i<32;++i) - pattern[i] = ~gStipples[stn][i]; - gFillPattern = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(), - (const char *)&pattern, 16, 16); - gdk_gc_set_stipple(gGCfill, gFillPattern); - current_fasi = fasi; - } - break; + break; - default: - gFillHollow = 1; + default: + ctxt->fillHollow = 1; } - fFillStyleModified = kFALSE; + ctxt->fAttFill.SetFillStyle(att.GetFillStyle()); } //////////////////////////////////////////////////////////////////////////////// @@ -3231,20 +3223,14 @@ void TGWin32::SetInput(int inp) void TGWin32::SetLineColor(Color_t cindex) { - if ((cindex < 0) || (cindex==fLineColor)) return; + if (cindex < 0) return; - fLineColor = cindex; - fLineColorModified = kTRUE; -} + TAttLine::SetLineColor(cindex); -//////////////////////////////////////////////////////////////////////////////// -/// + TAttLine arg(gCws->fAttLine); + arg.SetLineColor(cindex); -void TGWin32::UpdateLineColor() -{ - SetColor(gGCline, Int_t(fLineColor)); - SetColor(gGCdash, Int_t(fLineColor)); - fLineColorModified = kFALSE; + SetAttLine((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -3257,31 +3243,9 @@ void TGWin32::UpdateLineColor() /// e.g. N=4,DASH=(6,3,1,3) gives a dashed-dotted line with dash length 6 /// and a gap of 7 between dashes -void TGWin32::SetLineType(int n, int *dash) +void TGWin32::SetLineType(int /* n */ , int * /* dash */) { - if (n <= 0) { - gLineStyle = GDK_LINE_SOLID; - gdk_gc_set_line_attributes(gGCline, gLineWidth, - (GdkLineStyle)gLineStyle, - (GdkCapStyle) gCapStyle, - (GdkJoinStyle) gJoinStyle); - } else { - int i; - gDashSize = TMath::Min((int)sizeof(gDashList),n); - gDashLength = 0; - for (i = 0; i < gDashSize; i++) { - gDashList[i] = dash[i]; - gDashLength += gDashList[i]; - } - gDashOffset = 0; - gLineStyle = GDK_LINE_ON_OFF_DASH; - if (gLineWidth == 0) gLineWidth =1; - gdk_gc_set_line_attributes(gGCdash, gLineWidth, - (GdkLineStyle) gLineStyle, - (GdkCapStyle) gCapStyle, - (GdkJoinStyle) gJoinStyle); - } - fPenModified = kFALSE; + Warning("SetLineType", "DEPRECATED, use SetAttLine() instead"); } //////////////////////////////////////////////////////////////////////////////// @@ -3289,45 +3253,21 @@ void TGWin32::SetLineType(int n, int *dash) void TGWin32::SetLineStyle(Style_t lstyle) { - if (fLineStyle == lstyle) return; + TAttLine::SetLineStyle(lstyle); + + TAttLine arg(gCws->fAttLine); + arg.SetLineStyle(lstyle); - fLineStyle = lstyle; - fPenModified = kTRUE; + SetAttLine((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// Update line style +/// Return current line style +/// FIXME: Only as temporary solution while some code analyze current line style -void TGWin32::UpdateLineStyle() +Style_t TGWin32::GetLineStyle() const { - static Int_t dashed[2] = { 3, 3 }; - static Int_t dotted[2] = { 1, 2 }; - static Int_t dasheddotted[4] = { 3, 4, 1, 4 }; - - if (fLineStyle <= 1) { - SetLineType(0, 0); - } else if (fLineStyle == 2) { - SetLineType(2, dashed); - } else if (fLineStyle == 3) { - SetLineType(2, dotted); - } else if (fLineStyle == 4) { - SetLineType(4, dasheddotted); - } else { - TString st = (TString)gStyle->GetLineStyleString(fLineStyle); - TObjArray *tokens = st.Tokenize(" "); - Int_t nt; - nt = tokens->GetEntries(); - Int_t *linestyle = new Int_t[nt]; - for (Int_t j = 0; jAt(j))->GetName(), "%d", &it); - linestyle[j] = (Int_t)(it/4); - } - SetLineType(nt,linestyle); - delete [] linestyle; - delete tokens; - } - fPenModified = kFALSE; + return gCws ? gCws->fAttLine.GetLineStyle() : TAttLine::GetLineStyle(); } //////////////////////////////////////////////////////////////////////////////// @@ -3336,69 +3276,113 @@ void TGWin32::UpdateLineStyle() void TGWin32::SetLineWidth(Width_t width) { - if (fLineWidth == width) return; - fLineWidth = width; + TAttLine::SetLineWidth(width); - if (width == 1 && gLineStyle == GDK_LINE_SOLID) gLineWidth = 0; - else gLineWidth = width; + TAttLine arg(gCws->fAttLine); + arg.SetLineWidth(width); - fPenModified = kTRUE; + SetAttLine((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// Set color index for markers. +/// Return current line width +/// FIXME: Only as temporary solution while some code analyze current line wide -void TGWin32::SetMarkerColor(Color_t cindex) +Width_t TGWin32::GetLineWidth() const { - if ((cindex<0) || (cindex==fMarkerColor)) return; - fMarkerColor = cindex; - fMarkerColorModified = kTRUE; + return gCws ? gCws->fAttLine.GetLineWidth() : TAttLine::GetLineWidth(); } //////////////////////////////////////////////////////////////////////////////// -/// +/// Set line attributes for specified window. -void TGWin32::UpdateMarkerColor() +void TGWin32::SetAttLine(WinContext_t wctxt, const TAttLine &att) { - SetColor(gGCmark, Int_t(fMarkerColor)); - fMarkerColorModified = kFALSE; + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; + + SetColor(ctxt, ctxt->fGClist[kGCline], att.GetLineColor()); + SetColor(ctxt, ctxt->fGClist[kGCdash], att.GetLineColor()); + + if (ctxt->fAttLine.GetLineStyle() != att.GetLineStyle()) { //set style index only if different + if (att.GetLineStyle() <= 1) + ctxt->dashList.clear(); + else if (att.GetLineStyle() == 2) + ctxt->dashList = { 3, 3 }; + else if (att.GetLineStyle() == 3) + ctxt->dashList = { 1, 2 }; + else if (att.GetLineStyle() == 4) { + ctxt->dashList = { 3, 4, 1, 4} ; + } else { + TString st = (TString)gStyle->GetLineStyleString(att.GetLineStyle()); + auto tokens = st.Tokenize(" "); + Int_t nt = tokens->GetEntries(); + ctxt->dashList.resize(nt); + for (Int_t j = 0; j < nt; ++j) { + Int_t it; + sscanf(tokens->At(j)->GetName(), "%d", &it); + ctxt->dashList[j] = (Int_t) (it/4); + } + delete tokens; + } + ctxt->dashLength = 0; + for (auto elem : ctxt->dashList) + ctxt->dashLength += elem; + ctxt->dashOffset = 0; + ctxt->lineStyle = ctxt->dashList.size() == 0 ? GDK_LINE_SOLID : GDK_LINE_ON_OFF_DASH; + } + + ctxt->lineWidth = att.GetLineWidth(); + if (ctxt->lineWidth == 1 && ctxt->lineStyle == GDK_LINE_SOLID) + ctxt->lineWidth = 0; + + if (ctxt->lineStyle == GDK_LINE_SOLID) { + gdk_gc_set_line_attributes(ctxt->fGClist[kGCline], ctxt->lineWidth, + ctxt->lineStyle, + (GdkCapStyle) gCapStyle, + (GdkJoinStyle) gJoinStyle); + } else { + gdk_gc_set_line_attributes(ctxt->fGClist[kGCdash], ctxt->lineWidth, + ctxt->lineStyle, + (GdkCapStyle) gCapStyle, + (GdkJoinStyle) gJoinStyle); + } + + ctxt->fAttLine = att; } + //////////////////////////////////////////////////////////////////////////////// -/// Set marker size index. -/// msize : marker scale factor +/// Set color index for markers. -void TGWin32::SetMarkerSize(Float_t msize) +void TGWin32::SetMarkerColor(Color_t cindex) { - if ((msize==fMarkerSize) || (msize<0)) return; + if (cindex < 0) return; - fMarkerSize = msize; - SetMarkerStyle(-fMarkerStyle); + TAttMarker::SetMarkerColor(cindex); + + TAttMarker arg(gCws->fAttMarker); + arg.SetMarkerColor(cindex); + + SetAttMarker((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// Set marker type. -/// type : marker type -/// n : length of marker description -/// xy : list of points describing marker shape -/// -/// if n == 0 marker is a single point -/// if TYPE == 0 marker is hollow circle of diameter N -/// if TYPE == 1 marker is filled circle of diameter N -/// if TYPE == 2 marker is a hollow polygon describe by line XY -/// if TYPE == 3 marker is a filled polygon describe by line XY -/// if TYPE == 4 marker is described by segmented line XY -/// e.g. TYPE=4,N=4,XY=(-3,0,3,0,0,-3,0,3) sets a plus shape of 7x7 pixels +/// Set marker size index. +/// msize : marker scale factor -void TGWin32::SetMarkerType(int type, int n, GdkPoint * xy) +void TGWin32::SetMarkerSize(Float_t msize) { - gMarker.type = type; - gMarker.n = n < kMAXMK ? n : kMAXMK; - if (gMarker.type >= 2) { - for (int i = 0; i < gMarker.n; i++) { - gMarker.xy[i] = xy[i]; - } - } + if ((msize == TAttMarker::GetMarkerSize()) || (msize < 0)) + return; + + TAttMarker::SetMarkerSize(msize); + + TAttMarker arg(gCws->fAttMarker); + arg.SetMarkerSize(msize); + + SetAttMarker((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -3406,36 +3390,59 @@ void TGWin32::SetMarkerType(int type, int n, GdkPoint * xy) void TGWin32::SetMarkerStyle(Style_t markerstyle) { - if (fMarkerStyle == markerstyle) return; - fMarkerStyle = TMath::Abs(markerstyle); - fMarkerStyleModified = kTRUE; + if (TAttMarker::GetMarkerStyle() == markerstyle) + return; + + TAttMarker::SetMarkerStyle(markerstyle); + + TAttMarker arg(gCws->fAttMarker); + arg.SetMarkerStyle(markerstyle); + + SetAttMarker((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// +/// Set marker attributes for speicfied window -void TGWin32::UpdateMarkerStyle() +void TGWin32::SetAttMarker(WinContext_t wctxt, const TAttMarker &att) { - Style_t markerstyle = TAttMarker::GetMarkerStyleBase(fMarkerStyle); - gMarkerLineWidth = TAttMarker::GetMarkerLineWidth(fMarkerStyle); + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; + + SetColor(ctxt, ctxt->fGClist[kGCmark], att.GetMarkerColor()); + + Bool_t changed = (att.GetMarkerSize() != ctxt->fAttMarker.GetMarkerSize()) || + (att.GetMarkerStyle() != ctxt->fAttMarker.GetMarkerStyle()); + + ctxt->fAttMarker = att; + + if (!changed) + return; + + auto markerstyle = TAttMarker::GetMarkerStyleBase(att.GetMarkerStyle()); + ctxt->markerLineWidth = TAttMarker::GetMarkerLineWidth(att.GetMarkerStyle()); // The fast pixel markers need to be treated separately if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) { - gdk_gc_set_line_attributes(gGCmark, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); + gdk_gc_set_line_attributes(ctxt->fGClist[kGCmark], 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); } else { - gdk_gc_set_line_attributes(gGCmark, gMarkerLineWidth, - (GdkLineStyle) gMarkerLineStyle, - (GdkCapStyle) gMarkerCapStyle, - (GdkJoinStyle) gMarkerJoinStyle); + gdk_gc_set_line_attributes(ctxt->fGClist[kGCmark], ctxt->markerLineWidth, + (GdkLineStyle) gMarkerLineStyle, + (GdkCapStyle) gMarkerCapStyle, + (GdkJoinStyle) gMarkerJoinStyle); } - static GdkPoint shape[30]; + Float_t markerSizeReduced = att.GetMarkerSize() - TMath::Floor(ctxt->markerLineWidth/2.)/4.; + Int_t im = Int_t(4 * markerSizeReduced + 0.5); - Float_t MarkerSizeReduced = fMarkerSize - TMath::Floor(gMarkerLineWidth/2.)/4.; - Int_t im = Int_t(4 * MarkerSizeReduced + 0.5); + auto& shape = ctxt->markerShape; + ctxt->markerSize = 0; + ctxt->markerType = 0; if (markerstyle == 2) { // + shaped marker + shape.resize(4); shape[0].x = -im; shape[0].y = 0; shape[1].x = im; @@ -3444,9 +3451,10 @@ void TGWin32::UpdateMarkerStyle() shape[2].y = -im; shape[3].x = 0; shape[3].y = im; - SetMarkerType(4, 4, shape); + ctxt->markerType = 4; } else if (markerstyle == 3 || markerstyle == 31) { // * shaped marker + shape.resize(8); shape[0].x = -im; shape[0].y = 0; shape[1].x = im; @@ -3464,13 +3472,16 @@ void TGWin32::UpdateMarkerStyle() shape[6].y = im; shape[7].x = im; shape[7].y = -im; - SetMarkerType(4, 8, shape); + ctxt->markerType = 4; } else if (markerstyle == 4 || markerstyle == 24) { // O shaped marker - SetMarkerType(0, im * 2, shape); + shape.resize(0); + ctxt->markerType = 0; + ctxt->markerSize = im * 2; } else if (markerstyle == 5) { // X shaped marker im = Int_t(0.707 * Float_t(im) + 0.5); + shape.resize(4); shape[0].x = -im; shape[0].y = -im; shape[1].x = im; @@ -3479,9 +3490,10 @@ void TGWin32::UpdateMarkerStyle() shape[2].y = im; shape[3].x = im; shape[3].y = -im; - SetMarkerType(4, 4, shape); + ctxt->markerType = 4; } else if (markerstyle == 6) { // + shaped marker (with 1 pixel) + shape.resize(4); shape[0].x = -1; shape[0].y = 0; shape[1].x = 1; @@ -3490,9 +3502,10 @@ void TGWin32::UpdateMarkerStyle() shape[2].y = -1; shape[3].x = 0; shape[3].y = 1; - SetMarkerType(4, 4, shape); + ctxt->markerType = 4; } else if (markerstyle == 7) { // . shaped marker (with 9 pixel) + shape.resize(6); shape[0].x = -1; shape[0].y = 1; shape[1].x = 1; @@ -3505,12 +3518,15 @@ void TGWin32::UpdateMarkerStyle() shape[4].y = -1; shape[5].x = 1; shape[5].y = -1; - SetMarkerType(4, 6, shape); + ctxt->markerType = 4; } else if (markerstyle == 8 || markerstyle == 20) { // O shaped marker (filled) - SetMarkerType(1, im * 2, shape); + shape.resize(0); + ctxt->markerType = 0; + ctxt->markerSize = im * 2; } else if (markerstyle == 21) { // full square + shape.resize(5); shape[0].x = -im; shape[0].y = -im; shape[1].x = im; @@ -3521,9 +3537,10 @@ void TGWin32::UpdateMarkerStyle() shape[3].y = im; shape[4].x = -im; shape[4].y = -im; - SetMarkerType(3, 5, shape); + ctxt->markerType = 3; } else if (markerstyle == 22) { // full triangle up + shape.resize(4); shape[0].x = -im; shape[0].y = im; shape[1].x = im; @@ -3532,9 +3549,10 @@ void TGWin32::UpdateMarkerStyle() shape[2].y = -im; shape[3].x = -im; shape[3].y = im; - SetMarkerType(3, 4, shape); + ctxt->markerType = 3; } else if (markerstyle == 23) { // full triangle down + shape.resize(4); shape[0].x = 0; shape[0].y = im; shape[1].x = im; @@ -3543,9 +3561,10 @@ void TGWin32::UpdateMarkerStyle() shape[2].y = -im; shape[3].x = 0; shape[3].y = im; - SetMarkerType(3, 4, shape); + ctxt->markerType = 3; } else if (markerstyle == 25) { // open square + shape.resize(5); shape[0].x = -im; shape[0].y = -im; shape[1].x = im; @@ -3556,9 +3575,10 @@ void TGWin32::UpdateMarkerStyle() shape[3].y = im; shape[4].x = -im; shape[4].y = -im; - SetMarkerType(2, 5, shape); + ctxt->markerType = 2; } else if (markerstyle == 26) { // open triangle up + shape.resize(4); shape[0].x = -im; shape[0].y = im; shape[1].x = im; @@ -3567,10 +3587,11 @@ void TGWin32::UpdateMarkerStyle() shape[2].y = -im; shape[3].x = -im; shape[3].y = im; - SetMarkerType(2, 4, shape); + ctxt->markerType = 2; } else if (markerstyle == 27) { // open losange - Int_t imx = Int_t(2.66 * MarkerSizeReduced + 0.5); + Int_t imx = Int_t(2.66 * markerSizeReduced + 0.5); + shape.resize(5); shape[0].x = -imx; shape[0].y = 0; shape[1].x = 0; @@ -3581,10 +3602,11 @@ void TGWin32::UpdateMarkerStyle() shape[3].y = im; shape[4].x = -imx; shape[4].y = 0; - SetMarkerType(2, 5, shape); + ctxt->markerType = 2; } else if (markerstyle == 28) { // open cross - Int_t imx = Int_t(1.33 * MarkerSizeReduced + 0.5); + Int_t imx = Int_t(1.33 * markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = -im; shape[0].y = -imx; shape[1].x = -imx; @@ -3611,13 +3633,14 @@ void TGWin32::UpdateMarkerStyle() shape[11].y = imx; shape[12].x = -im; shape[12].y = -imx; - SetMarkerType(2, 13, shape); + ctxt->markerType = 2; } else if (markerstyle == 29) { // full star pentagone - Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5); - Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5); - Int_t im3 = Int_t(2.66 * MarkerSizeReduced + 0.5); - Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5); + Int_t im1 = Int_t(0.66 * markerSizeReduced + 0.5); + Int_t im2 = Int_t(2.00 * markerSizeReduced + 0.5); + Int_t im3 = Int_t(2.66 * markerSizeReduced + 0.5); + Int_t im4 = Int_t(1.33 * markerSizeReduced + 0.5); + shape.resize(11); shape[0].x = -im; shape[0].y = im4; shape[1].x = -im2; @@ -3640,13 +3663,14 @@ void TGWin32::UpdateMarkerStyle() shape[9].y = im4; shape[10].x = -im; shape[10].y = im4; - SetMarkerType(3, 11, shape); + ctxt->markerType = 3; } else if (markerstyle == 30) { // open star pentagone - Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5); - Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5); - Int_t im3 = Int_t(2.66 * MarkerSizeReduced + 0.5); - Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5); + Int_t im1 = Int_t(0.66 * markerSizeReduced + 0.5); + Int_t im2 = Int_t(2.00 * markerSizeReduced + 0.5); + Int_t im3 = Int_t(2.66 * markerSizeReduced + 0.5); + Int_t im4 = Int_t(1.33 * markerSizeReduced + 0.5); + shape.resize(11); shape[0].x = -im; shape[0].y = im4; shape[1].x = -im2; @@ -3669,26 +3693,29 @@ void TGWin32::UpdateMarkerStyle() shape[9].y = im4; shape[10].x = -im; shape[10].y = im4; - SetMarkerType(2, 11, shape); + ctxt->markerType = 2; } else if (markerstyle == 32) { // open triangle down + shape.resize(4); shape[0].x = 0; shape[0].y = im; shape[1].x = im; shape[1].y = -im; shape[2].x = -im; shape[2].y = -im; shape[3].x = 0; shape[3].y = im; - SetMarkerType(2,4,shape); + ctxt->markerType = 2; } else if (markerstyle == 33) { // full losange - Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5); + Int_t imx = Int_t(2.66*markerSizeReduced + 0.5); + shape.resize(5); shape[0].x =-imx; shape[0].y = 0; shape[1].x = 0; shape[1].y = -im; shape[2].x = imx; shape[2].y = 0; shape[3].x = 0; shape[3].y = im; shape[4].x =-imx; shape[4].y = 0; - SetMarkerType(3,5,shape); + ctxt->markerType = 3; } else if (markerstyle == 34) { // full cross - Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); + Int_t imx = Int_t(1.33*markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = -im; shape[0].y =-imx; shape[1].x =-imx; shape[1].y =-imx; shape[2].x =-imx; shape[2].y = -im; @@ -3702,9 +3729,10 @@ void TGWin32::UpdateMarkerStyle() shape[10].x=-imx; shape[10].y= imx; shape[11].x= -im; shape[11].y= imx; shape[12].x= -im; shape[12].y=-imx; - SetMarkerType(3,13,shape); + ctxt->markerType = 3; } else if (markerstyle == 35) { // square with diagonal cross + shape.resize(8); shape[0].x = -im; shape[0].y = -im; shape[1].x = im; shape[1].y = -im; shape[2].x = im; shape[2].y = im; @@ -3713,9 +3741,10 @@ void TGWin32::UpdateMarkerStyle() shape[5].x = im; shape[5].y = im; shape[6].x = -im; shape[6].y = im; shape[7].x = im; shape[7].y = -im; - SetMarkerType(2,8,shape); + ctxt->markerType = 2; } else if (markerstyle == 36) { // diamond with cross + shape.resize(8); shape[0].x =-im; shape[0].y = 0; shape[1].x = 0; shape[1].y = -im; shape[2].x = im; shape[2].y = 0; @@ -3724,10 +3753,11 @@ void TGWin32::UpdateMarkerStyle() shape[5].x = im; shape[5].y = 0; shape[6].x = 0; shape[6].y = im; shape[7].x = 0; shape[7].y =-im; - SetMarkerType(2,8,shape); + ctxt->markerType = 2; } else if (markerstyle == 37) { // open three triangles - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(10); shape[0].x = 0; shape[0].y = 0; shape[1].x =-im2; shape[1].y = im; shape[2].x = -im; shape[2].y = 0; @@ -3738,10 +3768,11 @@ void TGWin32::UpdateMarkerStyle() shape[7].x = im; shape[7].y = 0; shape[8].x = im2; shape[8].y = im; shape[9].x = 0; shape[9].y = 0; - SetMarkerType(2,10,shape); + ctxt->markerType = 2; } else if (markerstyle == 38) { // + shaped marker with octagon - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(15); shape[0].x = -im; shape[0].y = 0; shape[1].x = -im; shape[1].y =-im2; shape[2].x =-im2; shape[2].y =-im; @@ -3757,10 +3788,11 @@ void TGWin32::UpdateMarkerStyle() shape[12].x = 0; shape[12].y = -im; shape[13].x = 0; shape[13].y = im; shape[14].x = 0; shape[14].y = 0; - SetMarkerType(2,15,shape); + ctxt->markerType = 2; } else if (markerstyle == 39) { // filled three triangles - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(9); shape[0].x = 0; shape[0].y = 0; shape[1].x =-im2; shape[1].y = im; shape[2].x = -im; shape[2].y = 0; @@ -3770,10 +3802,11 @@ void TGWin32::UpdateMarkerStyle() shape[6].x = 0; shape[6].y = 0; shape[7].x = im; shape[7].y = 0; shape[8].x = im2; shape[8].y = im; - SetMarkerType(3,9,shape); + ctxt->markerType = 3; } else if (markerstyle == 40) { // four open triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = 0; shape[0].y = 0; shape[1].x = im2; shape[1].y = im; shape[2].x = im; shape[2].y = im2; @@ -3787,10 +3820,11 @@ void TGWin32::UpdateMarkerStyle() shape[10].x = -im; shape[10].y = im2; shape[11].x = -im2; shape[11].y = im; shape[12].x = 0; shape[12].y = 0; - SetMarkerType(2,13,shape); + ctxt->markerType = 2; } else if (markerstyle == 41) { // four filled triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = 0; shape[0].y = 0; shape[1].x = im2; shape[1].y = im; shape[2].x = im; shape[2].y = im2; @@ -3804,10 +3838,11 @@ void TGWin32::UpdateMarkerStyle() shape[10].x = -im; shape[10].y = im2; shape[11].x = -im2; shape[11].y = im; shape[12].x = 0; shape[12].y = 0; - SetMarkerType(3,13,shape); + ctxt->markerType = 3; } else if (markerstyle == 42) { // open double diamonds - Int_t imx = Int_t(MarkerSizeReduced + 0.5); + Int_t imx = Int_t(markerSizeReduced + 0.5); + shape.resize(9); shape[0].x= 0; shape[0].y= im; shape[1].x= -imx; shape[1].y= imx; shape[2].x = -im; shape[2].y = 0; @@ -3817,10 +3852,11 @@ void TGWin32::UpdateMarkerStyle() shape[6].x = im; shape[6].y = 0; shape[7].x= imx; shape[7].y= imx; shape[8].x= 0; shape[8].y= im; - SetMarkerType(2,9,shape); + ctxt->markerType = 2; } else if (markerstyle == 43) { // filled double diamonds - Int_t imx = Int_t(MarkerSizeReduced + 0.5); + Int_t imx = Int_t(markerSizeReduced + 0.5); + shape.resize(9); shape[0].x = 0; shape[0].y = im; shape[1].x = -imx; shape[1].y = imx; shape[2].x = -im; shape[2].y = 0; @@ -3830,10 +3866,11 @@ void TGWin32::UpdateMarkerStyle() shape[6].x = im; shape[6].y = 0; shape[7].x = imx; shape[7].y = imx; shape[8].x = 0; shape[8].y = im; - SetMarkerType(3,9,shape); + ctxt->markerType = 3; } else if (markerstyle == 44) { // open four triangles plus - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(11); shape[0].x = 0; shape[0].y = 0; shape[1].x = im2; shape[1].y = im; shape[2].x = -im2; shape[2].y = im; @@ -3845,11 +3882,12 @@ void TGWin32::UpdateMarkerStyle() shape[8].x = -im; shape[8].y = im2; shape[9].x = -im; shape[9].y = -im2; shape[10].x = 0; shape[10].y = 0; - SetMarkerType(2,11,shape); + ctxt->markerType = 2; } else if (markerstyle == 45) { // filled four triangles plus - Int_t im0 = Int_t(0.4*MarkerSizeReduced + 0.5); - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im0 = Int_t(0.4*markerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = im0; shape[0].y = im0; shape[1].x = im2; shape[1].y = im; shape[2].x = -im2; shape[2].y = im; @@ -3863,10 +3901,11 @@ void TGWin32::UpdateMarkerStyle() shape[10].x = im; shape[10].y = -im2; shape[11].x = im; shape[11].y = im2; shape[12].x = im0; shape[12].y = im0; - SetMarkerType(3,13,shape); + ctxt->markerType = 3; } else if (markerstyle == 46) { // open four triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = 0; shape[0].y = im2; shape[1].x = -im2; shape[1].y = im; shape[2].x = -im; shape[2].y = im2; @@ -3880,10 +3919,11 @@ void TGWin32::UpdateMarkerStyle() shape[10].x = im; shape[10].y = im2; shape[11].x = im2; shape[11].y = im; shape[12].x = 0; shape[12].y = im2; - SetMarkerType(2,13,shape); + ctxt->markerType = 2; } else if (markerstyle == 47) { // filled four triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(13); shape[0].x = 0; shape[0].y = im2; shape[1].x = -im2; shape[1].y = im; shape[2].x = -im; shape[2].y = im2; @@ -3897,10 +3937,11 @@ void TGWin32::UpdateMarkerStyle() shape[10].x = im; shape[10].y = im2; shape[11].x = im2; shape[11].y = im; shape[12].x = 0; shape[12].y = im2; - SetMarkerType(3,13,shape); + ctxt->markerType = 3; } else if (markerstyle == 48) { // four filled squares X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*markerSizeReduced + 0.5); + shape.resize(17); shape[0].x = 0; shape[0].y = im2*1.005; shape[1].x = -im2; shape[1].y = im; shape[2].x = -im; shape[2].y = im2; @@ -3918,10 +3959,11 @@ void TGWin32::UpdateMarkerStyle() shape[14].x = 0; shape[14].y = -im2*0.995; shape[15].x = -im2*0.995; shape[15].y = 0; shape[16].x = 0; shape[16].y = im2*0.995; - SetMarkerType(3,16,shape); + ctxt->markerType = 3; } else if (markerstyle == 49) { // four filled squares plus - Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); + Int_t imx = Int_t(1.33*markerSizeReduced + 0.5); + shape.resize(17); shape[0].x =-imx; shape[0].y =-imx*1.005; shape[1].x =-imx; shape[1].y = -im; shape[2].x = imx; shape[2].y = -im; @@ -3939,14 +3981,87 @@ void TGWin32::UpdateMarkerStyle() shape[14].x = imx; shape[14].y = imx; shape[15].x = imx; shape[15].y =-imx; shape[16].x =-imx; shape[16].y =-imx*1.005; - SetMarkerType(3,17,shape); + ctxt->markerType = 3; } else { // single dot - SetMarkerType(0, 0, shape); + shape.resize(0); + ctxt->markerType = 0; + ctxt->markerSize = 0; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set text attributes for speicfied window + +void TGWin32::SetAttText(WinContext_t wctxt, const TAttText &att) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; + + Int_t txalh = att.GetTextAlign() / 10; + Int_t txalv = att.GetTextAlign() % 10; + + ctxt->textAlign = kAlignNone; + + switch (txalh) { + case 0 : + case 1 : + switch (txalv) { //left + case 1 : + ctxt->textAlign = kBLeft; //bottom + break; + case 2 : + ctxt->textAlign = kMLeft; //middle + break; + case 3 : + ctxt->textAlign = kTLeft; //top + break; + } + break; + case 2 : + switch (txalv) { //center + case 1 : + ctxt->textAlign = kBCenter; //bottom + break; + case 2 : + ctxt->textAlign = kMCenter; //middle + break; + case 3 : + ctxt->textAlign = kTCenter; //top + break; + } + break; + case 3 : + switch (txalv) { //right + case 1 : + ctxt->textAlign = kBRight; //bottom + break; + case 2 : + ctxt->textAlign = kMRight; //center + break; + case 3 : + ctxt->textAlign = kTRight; //top + break; + } + break; } - fMarkerStyleModified = kFALSE; + + SetColor(ctxt, ctxt->fGClist[kGCtext], att.GetTextColor()); + + GdkGCValues values; + gdk_gc_get_values(ctxt->fGClist[kGCtext], &values); + gdk_gc_set_foreground(ctxt->fGClist[kGCinvt], &values.background); + gdk_gc_set_background(ctxt->fGClist[kGCinvt], &values.foreground); + gdk_gc_set_background(ctxt->fGClist[kGCtext], (GdkColor *) & GetColor(0).color); + + TTF::SetTextFont(att.GetTextFont()); + TTF::SetTextSize(att.GetTextSize()); + + ctxt->fAttText = att; } + //////////////////////////////////////////////////////////////////////////////// /// Set opacity of a window. This image manipulation routine works /// by adding to a percent amount of neutral to each pixels RGB. @@ -4001,7 +4116,7 @@ void TGWin32::SetOpacity(Int_t percent) } // put image back in pixmap on server - gdk_draw_image(gCws->drawing, gGCpxmp, (GdkImage *)image, + gdk_draw_image(gCws->drawing, gCws->fGClist[kGCpxmp], (GdkImage *)image, 0, 0, 0, 0, gCws->width, gCws->height); GdiFlush(); @@ -4132,59 +4247,12 @@ void TGWin32::SetRGB(int cindex, float r, float g, float b) void TGWin32::SetTextAlign(Short_t talign) { - static Short_t current = 0; - if (talign==current) return; - current = talign; - - Int_t txalh = talign / 10; - Int_t txalv = talign % 10; - fTextAlignH = txalh; - fTextAlignV = txalv; + TAttText::SetTextAlign(talign); - switch (txalh) { + TAttText arg(gCws->fAttText); + arg.SetTextAlign(talign); - case 0: - case 1: - switch (txalv) { //left - case 1: - fTextAlign = 7; //bottom - break; - case 2: - fTextAlign = 4; //center - break; - case 3: - fTextAlign = 1; //top - break; - } - break; - case 2: - switch (txalv) { //center - case 1: - fTextAlign = 8; //bottom - break; - case 2: - fTextAlign = 5; //center - break; - case 3: - fTextAlign = 2; //top - break; - } - break; - case 3: - switch (txalv) { //right - case 1: - fTextAlign = 9; //bottom - break; - case 2: - fTextAlign = 6; //center - break; - case 3: - fTextAlign = 3; //top - break; - } - break; - } - TAttText::SetTextAlign(fTextAlign); + SetAttText((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -4192,23 +4260,19 @@ void TGWin32::SetTextAlign(Short_t talign) void TGWin32::SetTextColor(Color_t cindex) { - static Int_t current = 0; - GdkGCValues values; - if ((cindex < 0) || (Int_t(cindex)==current)) return; + if (cindex < 0) return; TAttText::SetTextColor(cindex); - SetColor(gGCtext, Int_t(cindex)); - gdk_gc_get_values(gGCtext, &values); - gdk_gc_set_foreground(gGCinvt, &values.background); - gdk_gc_set_background(gGCinvt, &values.foreground); - gdk_gc_set_background(gGCtext, (GdkColor *) & GetColor(0).color); - current = Int_t(cindex); + TAttText arg(gCws->fAttText); + arg.SetTextColor(cindex); + + SetAttText((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -void TGWin32::Sync(int mode) +void TGWin32::Sync(int /* mode */) { } @@ -4223,9 +4287,25 @@ void TGWin32::Sync(int mode) void TGWin32::UpdateWindow(int mode) { - if (gCws && gCws->double_buffer) { - gdk_window_copy_area(gCws->window, gGCpxmp, 0, 0, - gCws->drawing, 0, 0, gCws->width, gCws->height); + UpdateWindowW((WinContext_t) gCws, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Update current window +/// mode : (1) update +/// (0) sync +/// +/// Synchronise client and server once (not permanent). +/// Copy the pixmap ctxt->drawing on the window ctxt->window +/// if the double buffer is on. + +void TGWin32::UpdateWindowW(WinContext_t wctxt, Int_t mode) +{ + auto ctxt = (XWindow_t *) wctxt; + + if (ctxt && ctxt->double_buffer) { + gdk_window_copy_area(ctxt->window, ctxt->fGClist[kGCpxmp], 0, 0, + ctxt->drawing, 0, 0, ctxt->width, ctxt->height); } Update(mode); } @@ -4268,8 +4348,8 @@ void TGWin32::WritePixmap(int wid, unsigned int w, unsigned int h, wval = w; hval = h; - if (!fWindows) return; - gTws = &fWindows[wid]; + if (fWindows.count(wid) == 0) return; + gTws = fWindows[wid].get(); // XWriteBitmapFile(fDisplay,pxname,(Pixmap)gTws->drawing,wval,hval,-1,-1); } @@ -4457,11 +4537,14 @@ void TGWin32::PutImage(Int_t offset, Int_t itran, Int_t x0, Int_t y0, Int_t nx, int nlines[256]; GdkSegment lines[256][MAX_SEGMENT]; GdkDrawable *id; + GdkGC *lineGC; if (wid) { - id = (GdkDrawable*)wid; + id = (GdkDrawable*) wid; + lineGC = gdk_gc_new(GDK_ROOT_PARENT()); } else { id = gCws->drawing; + lineGC = gCws->fGClist[kGCline]; } for (i = 0; i < 256; i++) nlines[i] = 0; @@ -4484,8 +4567,8 @@ void TGWin32::PutImage(Int_t offset, Int_t itran, Int_t x0, Int_t y0, Int_t nx, lines[icol][n].x2 = x - 1; lines[icol][n].y2 = y; if (nlines[icol] == MAX_SEGMENT) { - SetColor(gGCline, (int) icol + offset); - gdk_win32_draw_segments(id, (GdkGC *) gGCline, + SetColor(wid ? nullptr : gCws, lineGC, (int) icol + offset); + gdk_win32_draw_segments(id, lineGC, (GdkSegment *) &lines[icol][0], MAX_SEGMENT); nlines[icol] = 0; } @@ -4501,8 +4584,8 @@ void TGWin32::PutImage(Int_t offset, Int_t itran, Int_t x0, Int_t y0, Int_t nx, lines[icol][n].x2 = x - 1; lines[icol][n].y2 = y; if (nlines[icol] == MAX_SEGMENT) { - SetColor(gGCline, (int) icol + offset); - gdk_win32_draw_segments(id, (GdkGC *) gGCline, + SetColor(wid ? nullptr : gCws, lineGC, (int) icol + offset); + gdk_win32_draw_segments(id, lineGC, (GdkSegment *)&lines[icol][0], MAX_SEGMENT); nlines[icol] = 0; } @@ -4511,11 +4594,15 @@ void TGWin32::PutImage(Int_t offset, Int_t itran, Int_t x0, Int_t y0, Int_t nx, for (i = 0; i < 256; i++) { if (nlines[i] != 0) { - SetColor(gGCline, i + offset); - gdk_win32_draw_segments(id, (GdkGC *) gGCline, - (GdkSegment *)&lines[icol][0], nlines[i]); + SetColor(wid ? nullptr : gCws, lineGC, i + offset); + gdk_win32_draw_segments(id, lineGC, + (GdkSegment *)&lines[icol][0], nlines[i]); } } + + if (wid) + gdk_gc_unref(lineGC); + } //////////////////////////////////////////////////////////////////////////////// @@ -4726,6 +4813,10 @@ void TGWin32::MoveWindow(Window_t id, Int_t x, Int_t y) { if (!id) return; + // prevent hiding the titlebar + if (x == 0 && y == 0) { + x = 1; y = 1; + } gdk_window_move((GdkDrawable *) id, x, y); } @@ -4737,6 +4828,10 @@ void TGWin32::MoveResizeWindow(Window_t id, Int_t x, Int_t y, UInt_t w, { if (!id) return; + // prevent hiding the titlebar + if (x == 0 && y == 0) { + x = 1; y = 1; + } gdk_window_move_resize((GdkWindow *) id, x, y, w, h); } @@ -6585,6 +6680,10 @@ void TGWin32::SetWMPosition(Window_t id, Int_t x, Int_t y) { if (!id) return; + // prevent hiding the titlebar + if (x == 0 && y == 0) { + x = 1; y = 1; + } gdk_window_move((GdkDrawable *) id, x, y); } @@ -7440,34 +7539,16 @@ Int_t TGWin32::AddPixmap(Window_t pix, UInt_t w, UInt_t h) SetBitmapDimensionEx(hBmp, w, h, &sz); GdkPixmap *newPix = gdk_pixmap_foreign_new(reinterpret_cast(hBmp)); - Int_t wid = 0; - for(; wid < fMaxNumberOfWindows; ++wid) - if (!fWindows[wid].open) - break; - - if (wid == fMaxNumberOfWindows) { - Int_t newSize = fMaxNumberOfWindows + 10; - - fWindows = (XWindow_t *)TStorage::ReAlloc(fWindows, newSize * sizeof(XWindow_t), - fMaxNumberOfWindows * sizeof(XWindow_t)); + Int_t wid = AddWindowHandle(); - for (Int_t i = fMaxNumberOfWindows; i < newSize; ++i) - fWindows[i].open = 0; - - fMaxNumberOfWindows = newSize; - } - - fWindows[wid].open = 1; - gCws = fWindows + wid; + gCws = fWindows[wid].get(); + gCws->ispixmap = 1; gCws->window = newPix; gCws->drawing = gCws->window; - gCws->buffer = 0; gCws->double_buffer = 0; - gCws->ispixmap = 1; gCws->clip = 0; gCws->width = w; gCws->height = h; - gCws->new_colors = 0; return wid; } @@ -7477,82 +7558,41 @@ Int_t TGWin32::AddPixmap(Window_t pix, UInt_t w, UInt_t h) Int_t TGWin32::AddWindow(ULongptr_t qwid, UInt_t w, UInt_t h) { - Int_t wid; - // Select next free window number + Int_t wid = AddWindowHandle(); - again: - for (wid = 0; wid < fMaxNumberOfWindows; wid++) { - if (!fWindows[wid].open) { - fWindows[wid].open = 1; - fWindows[wid].double_buffer = 0; - gCws = &fWindows[wid]; - break; - } - } - - if (wid == fMaxNumberOfWindows) { - int newsize = fMaxNumberOfWindows + 10; - fWindows = - (XWindow_t *) TStorage::ReAlloc(fWindows, - newsize * sizeof(XWindow_t), - fMaxNumberOfWindows * - sizeof(XWindow_t)); - - for (int i = fMaxNumberOfWindows; i < newsize; i++) { - fWindows[i].open = 0; - } + gCws = fWindows[wid].get(); - fMaxNumberOfWindows = newsize; - goto again; - } + gCws->shared = true; + gCws->ispixmap = 0; gCws->window = gdk_window_foreign_new(qwid); gCws->drawing = gCws->window; - gCws->buffer = 0; gCws->double_buffer = 0; - gCws->ispixmap = 0; gCws->clip = 0; gCws->width = w; gCws->height = h; - gCws->new_colors = 0; return wid; } //////////////////////////////////////////////////////////////////////////////// -/// Remove a window created by Qt (like CloseWindow1()). +/// Remove a window created by Qt. void TGWin32::RemoveWindow(ULongptr_t qwid) { - int wid; - SelectWindow((int)qwid); + CloseWindow(); +} - if (gCws->buffer) { - gdk_pixmap_unref(gCws->buffer); - } - if (gCws->new_colors) { - gdk_colormap_free_colors((GdkColormap *) fColormap, - (GdkColor *)gCws->new_colors, gCws->ncolors); - - delete [] gCws->new_colors; - gCws->new_colors = 0; - } - - GdiFlush(); - gCws->open = 0; - - if (!fWindows) return; +//////////////////////////////////////////////////////////////////////////////// +/// Returns window context for specified win id - // make first window in list the current window - for (wid = 0; wid < fMaxNumberOfWindows; wid++) { - if (fWindows[wid].open) { - gCws = &fWindows[wid]; - return; - } - } - gCws = 0; +WinContext_t TGWin32::GetWindowContext(Int_t wid) +{ + if (fWindows.count(wid) == 0) + return (WinContext_t) nullptr; + return (WinContext_t) fWindows[wid].get(); } //////////////////////////////////////////////////////////////////////////////// @@ -7845,3 +7885,37 @@ void TGWin32::SetUserThreadId(ULong_t id) } } +//////////////////////////////////////////////////////////////////////////////// +/// Set window draw mode + +void TGWin32::SetDrawModeW(WinContext_t wctxt, EDrawMode mode) +{ + // set TVirtualX member to support old interface + fDrawMode = mode; + + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; + + GdkFunction func = GDK_COPY; + if (mode == kXor) + func = GDK_XOR; + else if (mode == kInvert) + func = GDK_INVERT; + + for (int i = 0; i < kMAXGC; i++) { + if (ctxt->fGClist[i]) + gdk_gc_set_function(ctxt->fGClist[i], func); + } + + ctxt->drawMode = mode; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns window draw mode + +TVirtualX::EDrawMode TGWin32::GetDrawModeW(WinContext_t wctxt) +{ + auto ctxt = (XWindow_t *) wctxt; + return ctxt ? ctxt->drawMode : kCopy; +} diff --git a/graf2d/x11/inc/TGX11.h b/graf2d/x11/inc/TGX11.h index 17c524175761d..6d016d8e3cdf6 100644 --- a/graf2d/x11/inc/TGX11.h +++ b/graf2d/x11/inc/TGX11.h @@ -13,6 +13,8 @@ #define ROOT_TGX11 #include "TVirtualX.h" +#include +#include #ifdef Status // Convert Status from a CPP macro to a typedef: @@ -44,26 +46,6 @@ struct RXSetWindowAttributes; struct RXVisualInfo; struct RVisual; -/// Description of a X11 window. -struct XWindow_t { - Int_t fOpen; ///< 1 if the window is open, 0 if not - Int_t fDoubleBuffer; ///< 1 if the double buffer is on, 0 if not - Int_t fIsPixmap; ///< 1 if pixmap, 0 if not - Drawable fDrawing; ///< drawing area, equal to window or buffer - Drawable fWindow; ///< X11 window - Drawable fBuffer; ///< pixmap used for double buffer - UInt_t fWidth; ///< width of the window - UInt_t fHeight; ///< height of the window - Int_t fClip; ///< 1 if the clipping is on - Int_t fXclip; ///< x coordinate of the clipping rectangle - Int_t fYclip; ///< y coordinate of the clipping rectangle - UInt_t fWclip; ///< width of the clipping rectangle - UInt_t fHclip; ///< height of the clipping rectangle - ULong_t *fNewColors; ///< new image colors (after processing) - Int_t fNcolors; ///< number of different colors - Bool_t fShared; ///< notify when window is shared -}; - /// Description of a X11 color. struct XColor_t { ULong_t fPixel; ///< color pixel value @@ -76,29 +58,27 @@ struct XColor_t { class TExMap; +struct XWindow_t; + class TGX11 : public TVirtualX { +friend struct XWindow_t; + private: - Int_t fMaxNumberOfWindows; ///< Maximum number of windows - XWindow_t *fWindows; ///< List of windows + std::unordered_map> fWindows; // map of windows TExMap *fColors; ///< Hash list of colors Cursor fCursors[kNumCursors]; ///< List of cursors void *fXEvent; ///< Current native (X11) event - void CloseWindow1(); - void ClearPixmap(Drawable *pix); - void CopyWindowtoPixmap(Drawable *pix, Int_t xpos, Int_t ypos); + Int_t AddWindowHandle(); void FindBestVisual(); void FindUsableVisual(RXVisualInfo *vlist, Int_t nitems); void PutImage(Int_t offset, Int_t itran, Int_t x0, Int_t y0, Int_t nx, Int_t ny, Int_t xmin, Int_t ymin, Int_t xmax, Int_t ymax, UChar_t *image, Drawable_t id); - void RemovePixmap(Drawable *pix); - void SetColor(void *gc, Int_t ci); - void SetFillStyleIndex(Int_t style, Int_t fasi); + void SetColor(XWindow_t *ctxt, void *gc, Int_t ci); void SetInput(Int_t inp); - void SetMarkerType(Int_t type, Int_t n, RXPoint *xy); void CollectImageColors(ULong_t pixel, ULong_t *&orgcolors, Int_t &ncolors, Int_t &maxcolors); void MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors); @@ -130,9 +110,6 @@ class TGX11 : public TVirtualX { ULong_t fBlackPixel; ///< Value of black pixel in colormap ULong_t fWhitePixel; ///< Value of white pixel in colormap Int_t fScreenNumber; ///< Screen number - Int_t fTextAlignH; ///< Text Alignment Horizontal - Int_t fTextAlignV; ///< Text Alignment Vertical - Int_t fTextAlign; ///< Text alignment (set in SetTextAlign) Float_t fCharacterUpX; ///< Character Up vector along X Float_t fCharacterUpY; ///< Character Up vector along Y Float_t fTextMagnitude; ///< Text Magnitude @@ -147,14 +124,25 @@ class TGX11 : public TVirtualX { Bool_t fHasXft; ///< True when XftFonts are used // needed by TGX11TTF + enum EAlign { + kAlignNone, + kTLeft, kTCenter, kTRight, kMLeft, kMCenter, kMRight, + kBLeft, kBCenter, kBRight }; + Bool_t AllocColor(Colormap cmap, RXColor *color); void QueryColors(Colormap cmap, RXColor *colors, Int_t ncolors); void *GetGC(Int_t which) const; + Window_t GetWindow(WinContext_t wctxt) const; + void *GetGCW(WinContext_t wctxt, Int_t which) const; + EAlign GetTextAlignW(WinContext_t wctxt) const; + XColor_t &GetColor(Int_t cid); + TGX11(TGX11 &&org); + TGX11(const TGX11 &org) = delete; + public: TGX11(); - TGX11(const TGX11 &org); TGX11(const char *name, const char *title); ~TGX11() override; @@ -163,15 +151,6 @@ class TGX11 : public TVirtualX { void ClosePixmap() override; void CloseWindow() override; void CopyPixmap(Int_t wid, Int_t xpos, Int_t ypos) override; - void DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) override; - void DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx, Int_t ny, Int_t *ic) override; - void DrawFillArea(Int_t n, TPoint *xy) override; - void DrawLine(Int_t x1, Int_t y1, Int_t x2, Int_t y2) override; - void DrawPolyLine(Int_t n, TPoint *xy) override; - void DrawLinesSegments(Int_t n, TPoint *xy) override; - void DrawPolyMarker(Int_t n, TPoint *xy) override; - void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; - void DrawText(Int_t, Int_t, Float_t, Float_t, const wchar_t *, ETextMode) override {} void GetCharacterUp(Float_t &chupx, Float_t &chupy) override; Int_t GetDoubleBuffer(Int_t wid) override; void GetGeometry(Int_t wid, Int_t &x, Int_t &y, UInt_t &w, UInt_t &h) override; @@ -208,12 +187,24 @@ class TGX11 : public TVirtualX { void SetDoubleBufferOFF() override; void SetDoubleBufferON() override; void SetDrawMode(EDrawMode mode) override; + void Sync(Int_t mode) override; + void UpdateWindow(Int_t mode) override; + void Warp(Int_t ix, Int_t iy, Window_t id = 0) override; + Int_t WriteGIF(char *name) override; + void WritePixmap(Int_t wid, UInt_t w, UInt_t h, char *pxname) override; + Window_t GetCurrentWindow() const override; + Int_t SupportsExtension(const char *ext) const override; + + //---- Methods used for old graphics ----- void SetFillColor(Color_t cindex) override; void SetFillStyle(Style_t style) override; + Style_t GetFillStyle() const override; void SetLineColor(Color_t cindex) override; void SetLineType(Int_t n, Int_t *dash) override; void SetLineStyle(Style_t linestyle) override; + Style_t GetLineStyle() const override; void SetLineWidth(Width_t width) override; + Width_t GetLineWidth() const override; void SetMarkerColor(Color_t cindex) override; void SetMarkerSize(Float_t markersize) override; void SetMarkerStyle(Style_t markerstyle) override; @@ -225,13 +216,35 @@ class TGX11 : public TVirtualX { void SetTextFont(Font_t fontnumber) override; void SetTextMagnitude(Float_t mgn=1) override { fTextMagnitude = mgn;} void SetTextSize(Float_t textsize) override; - void Sync(Int_t mode) override; - void UpdateWindow(Int_t mode) override; - void Warp(Int_t ix, Int_t iy, Window_t id = 0) override; - Int_t WriteGIF(char *name) override; - void WritePixmap(Int_t wid, UInt_t w, UInt_t h, char *pxname) override; - Window_t GetCurrentWindow() const override; - Int_t SupportsExtension(const char *ext) const override; + void DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) override; + void DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx, Int_t ny, Int_t *ic) override; + void DrawFillArea(Int_t n, TPoint *xy) override; + void DrawLine(Int_t x1, Int_t y1, Int_t x2, Int_t y2) override; + void DrawPolyLine(Int_t n, TPoint *xy) override; + void DrawLinesSegments(Int_t n, TPoint *xy) override; + void DrawPolyMarker(Int_t n, TPoint *xy) override; + void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; + void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode) override; + + //---- Methods used for new graphics ----- + WinContext_t GetWindowContext(Int_t wid) override; + void SetAttFill(WinContext_t wctxt, const TAttFill &att) override; + void SetAttLine(WinContext_t wctxt, const TAttLine &att) override; + void SetAttMarker(WinContext_t wctxt, const TAttMarker &att) override; + void SetAttText(WinContext_t wctxt, const TAttText &att) override; + void SetDrawModeW(WinContext_t wctxt, EDrawMode mode) override; + EDrawMode GetDrawModeW(WinContext_t wctxt) override; + void ClearWindowW(WinContext_t wctxt) override; + void UpdateWindowW(WinContext_t wctxt, Int_t mode) override; + + void DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) override; + void DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2) override; + void DrawPolyLineW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xy) override; + void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; + void DrawTextW(WinContext_t, Int_t, Int_t, Float_t, Float_t, const wchar_t *, ETextMode) override {} //---- Methods used for GUI ----- void GetWindowAttributes(Window_t id, WindowAttributes_t &attr) override; diff --git a/graf2d/x11/src/TGX11.cxx b/graf2d/x11/src/TGX11.cxx index 9ba0fc6849e8f..dac0cdc595ce9 100644 --- a/graf2d/x11/src/TGX11.cxx +++ b/graf2d/x11/src/TGX11.cxx @@ -76,30 +76,66 @@ extern int XRotDrawAlignedImageString(Display*, XFontStruct*, float, extern XPoint *XRotTextExtents(Display*, XFontStruct*, float, int, int, char*, int); -//---- globals - -static XWindow_t *gCws; // gCws: pointer to the current window -static XWindow_t *gTws; // gTws: temporary pointer -const Int_t kBIGGEST_RGB_VALUE = 65535; // // Primitives Graphic Contexts global for all windows // -const int kMAXGC = 7; -static GC gGClist[kMAXGC]; -static GC *gGCline = &gGClist[0]; // PolyLines -static GC *gGCmark = &gGClist[1]; // PolyMarker -static GC *gGCfill = &gGClist[2]; // Fill areas -static GC *gGCtext = &gGClist[3]; // Text -static GC *gGCinvt = &gGClist[4]; // Inverse text -static GC *gGCdash = &gGClist[5]; // Dashed lines -static GC *gGCpxmp = &gGClist[6]; // Pixmap management +const int kMAXGC = 7, + kGCline = 0, kGCmark = 1, kGCfill = 2, + kGCtext = 3, kGCinvt = 4, kGCdash = 5, kGCpxmp = 6; static GC gGCecho; // Input echo -static Int_t gFillHollow; // Flag if fill style is hollow -static Pixmap gFillPattern = 0; // Fill pattern + +/// Description of a X11 window. +struct XWindow_t { + Int_t fOpen = 0; ///< 1 if the window is open, 0 if not + Int_t fDoubleBuffer = 0; ///< 1 if the double buffer is on, 0 if not + Int_t fIsPixmap = 0; ///< 1 if pixmap, 0 if not + Drawable fDrawing = 0; ///< drawing area, equal to window or buffer + Drawable fWindow = 0; ///< X11 window + Drawable fBuffer = 0; ///< pixmap used for double buffer + UInt_t fWidth = 0; ///< width of the window + UInt_t fHeight = 0; ///< height of the window + Int_t fClip = 0; ///< 1 if the clipping is on + Int_t fXclip = 0; ///< x coordinate of the clipping rectangle + Int_t fYclip = 0; ///< y coordinate of the clipping rectangle + UInt_t fWclip = 0; ///< width of the clipping rectangle + UInt_t fHclip = 0; ///< height of the clipping rectangle + ULong_t *fNewColors = 0; ///< new image colors (after processing) + Int_t fNcolors = 0; ///< number of different colors + Bool_t fShared = 0; ///< notify when window is shared + GC fGClist[kMAXGC]; ///< list of GC object, individual for each window + TVirtualX::EDrawMode drawMode = TVirtualX::kCopy; ///< current draw mode + TAttLine fAttLine = {-1, -1, -1}; ///< current line attributes + Int_t lineWidth = 0; ///< X11 line width + Int_t lineStyle = LineSolid; ///< X11 line style + std::vector dashList; ///< X11 array for dashes + Int_t dashLength = 0; ///< total length of dashes + Int_t dashOffset = 0; ///< current dash offset + TAttFill fAttFill = {-1, -1}; ///< current fill attributes + Int_t fillHollow = 0; ///< X11 fill method + Int_t fillFasi = 0; ///< selected fasi pattern + Pixmap fillPattern = 0; ///< current initialized fill pattern + TAttMarker fAttMarker = { -1, -1, -1 }; ///< current marker attribute + Int_t markerType = 0; ///< 4 differen kinds of marker + Int_t markerSize = 0; ///< size of simple markers + std::vector markerShape; ///< marker shape points + Int_t markerLineWidth = 0; ///< line width used for marker + TAttText fAttText; ///< current text attribute + TGX11::EAlign textAlign = TGX11::kAlignNone; ///< selected text align + XFontStruct *textFont = nullptr; ///< selected text font +}; + + +//---- globals + +static XWindow_t *gCws; // gCws: pointer to the current window +static XWindow_t *gTws; // gTws: temporary pointer + +const Int_t kBIGGEST_RGB_VALUE = 65535; + // // Text management @@ -113,16 +149,6 @@ static struct { static XFontStruct *gTextFont; // Current font static Int_t gCurrentFontNumber = 0; // Current font number in gFont[] -// -// Markers -// -const Int_t kMAXMK = 100; -static struct { - int type; - int n; - XPoint xy[kMAXMK]; -} gMarker; // Point list to draw marker -static int gMarkerLineWidth = 0; static int gMarkerLineStyle = LineSolid; static int gMarkerCapStyle = CapRound; static int gMarkerJoinStyle = JoinRound; @@ -130,14 +156,8 @@ static int gMarkerJoinStyle = JoinRound; // // Keep style values for line GC // -static int gLineWidth = 0; -static int gLineStyle = LineSolid; static int gCapStyle = CapButt; static int gJoinStyle = JoinMiter; -static char gDashList[10]; -static int gDashLength = 0; -static int gDashOffset = 0; -static int gDashSize = 0; // // Event masks @@ -180,7 +200,6 @@ TGX11::TGX11() fColormap = 0; fBlackPixel = 0; fWhitePixel = 0; - fWindows = nullptr; fColors = nullptr; fXEvent = new XEvent; fRedDiv = -1; @@ -194,10 +213,6 @@ TGX11::TGX11() fDepth = 0; fHasTTFonts = kFALSE; fHasXft = kFALSE; - fMaxNumberOfWindows = 10; - fTextAlignH = 1; - fTextAlignV = 1; - fTextAlign = 7; fTextMagnitude = 1; for (i = 0; i < kNumCursors; i++) fCursors[i] = 0; } @@ -229,17 +244,9 @@ TGX11::TGX11(const char *name, const char *title) : TVirtualX(name, title) fDepth = 0; fHasTTFonts = kFALSE; fHasXft = kFALSE; - fMaxNumberOfWindows = 10; - fTextAlignH = 1; - fTextAlignV = 1; - fTextAlign = 7; fTextMagnitude = 1; - for (i = 0; i < kNumCursors; i++) fCursors[i] = 0; - - //fWindows = new XWindow_t[fMaxNumberOfWindows]; - fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t)); - for (i = 0; i < fMaxNumberOfWindows; i++) - fWindows[i].fOpen = 0; + for (i = 0; i < kNumCursors; i++) + fCursors[i] = 0; fColors = new TExMap; } @@ -247,10 +254,8 @@ TGX11::TGX11(const char *name, const char *title) : TVirtualX(name, title) //////////////////////////////////////////////////////////////////////////////// /// Copy constructor. Currently only used by TGX11TTF. -TGX11::TGX11(const TGX11 &org) : TVirtualX(org) +TGX11::TGX11(TGX11 &&org) : TVirtualX(org) { - int i; - fDisplay = org.fDisplay; fScreenNumber = org.fScreenNumber; fVisual = org.fVisual; @@ -261,9 +266,6 @@ TGX11::TGX11(const TGX11 &org) : TVirtualX(org) fWhitePixel = org.fWhitePixel; fHasTTFonts = org.fHasTTFonts; fHasXft = org.fHasXft; - fTextAlignH = org.fTextAlignH; - fTextAlignV = org.fTextAlignV; - fTextAlign = org.fTextAlign; fTextMagnitude = org.fTextMagnitude; fCharacterUpX = org.fCharacterUpX; fCharacterUpY = org.fCharacterUpY; @@ -275,45 +277,14 @@ TGX11::TGX11(const TGX11 &org) : TVirtualX(org) fGreenShift = org.fGreenShift; fBlueShift = org.fBlueShift; fDrawMode = org.fDrawMode; - fXEvent = new XEvent; - - fMaxNumberOfWindows = org.fMaxNumberOfWindows; - //fWindows = new XWindow_t[fMaxNumberOfWindows]; - fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t)); - for (i = 0; i < fMaxNumberOfWindows; i++) { - fWindows[i].fOpen = org.fWindows[i].fOpen; - fWindows[i].fDoubleBuffer = org.fWindows[i].fDoubleBuffer; - fWindows[i].fIsPixmap = org.fWindows[i].fIsPixmap; - fWindows[i].fDrawing = org.fWindows[i].fDrawing; - fWindows[i].fWindow = org.fWindows[i].fWindow; - fWindows[i].fBuffer = org.fWindows[i].fBuffer; - fWindows[i].fWidth = org.fWindows[i].fWidth; - fWindows[i].fHeight = org.fWindows[i].fHeight; - fWindows[i].fClip = org.fWindows[i].fClip; - fWindows[i].fXclip = org.fWindows[i].fXclip; - fWindows[i].fYclip = org.fWindows[i].fYclip; - fWindows[i].fWclip = org.fWindows[i].fWclip; - fWindows[i].fHclip = org.fWindows[i].fHclip; - fWindows[i].fNewColors = org.fWindows[i].fNewColors; - fWindows[i].fNcolors = org.fWindows[i].fNcolors; - fWindows[i].fShared = org.fWindows[i].fShared; - } + fXEvent = org.fXEvent; org.fXEvent = nullptr; + fColors = org.fColors; org.fColors = nullptr; - for (i = 0; i < kNumCursors; i++) - fCursors[i] = org.fCursors[i]; + fWindows = std::move(org.fWindows); - fColors = new TExMap; - Long64_t key, value; - TExMapIter it(org.fColors); - while (it.Next(key, value)) { - XColor_t *colo = (XColor_t *) (Long_t)value; - XColor_t *col = new XColor_t; - col->fPixel = colo->fPixel; - col->fRed = colo->fRed; - col->fGreen = colo->fGreen; - col->fBlue = colo->fBlue; - col->fDefined = colo->fDefined; - fColors->Add(key, (Long_t) col); + for (int i = 0; i < kNumCursors; i++) { + fCursors[i] = org.fCursors[i]; + org.fCursors[i] = 0; } } @@ -322,17 +293,22 @@ TGX11::TGX11(const TGX11 &org) : TVirtualX(org) TGX11::~TGX11() { - delete (XEvent*)fXEvent; - if (fWindows) TStorage::Dealloc(fWindows); + if (fXEvent) + delete (XEvent*)fXEvent; - if (!fColors) return; - Long64_t key, value; - TExMapIter it(fColors); - while (it.Next(key, value)) { - XColor_t *col = (XColor_t *) (Long_t)value; - delete col; + if (fColors) { + Long64_t key, value; + TExMapIter it(fColors); + while (it.Next(key, value)) { + XColor_t *col = (XColor_t *) (Long_t)value; + delete col; + } + delete fColors; } - delete fColors; + + for (int i = 0; i < kNumCursors; i++) + if (fCursors[i]) + XFreeCursor((Display*)fDisplay, fCursors[i]); } //////////////////////////////////////////////////////////////////////////////// @@ -340,7 +316,8 @@ TGX11::~TGX11() Bool_t TGX11::Init(void *display) { - if (OpenDisplay(display) == -1) return kFALSE; + if (OpenDisplay(display) == -1) + return kFALSE; return kTRUE; } @@ -400,37 +377,33 @@ void TGX11::QueryColors(Colormap cmap, RXColor *color, Int_t ncolors) } } + //////////////////////////////////////////////////////////////////////////////// -/// Clear the pixmap pix. +/// Clear current window. -void TGX11::ClearPixmap(Drawable *pix) +void TGX11::ClearWindow() { - Window root; - int xx, yy; - unsigned int ww, hh, border, depth; - XGetGeometry((Display*)fDisplay, *pix, &root, &xx, &yy, &ww, &hh, &border, &depth); - SetColor(gGCpxmp, 0); - XFillRectangle((Display*)fDisplay, *pix, *gGCpxmp, 0 ,0 ,ww ,hh); - SetColor(gGCpxmp, 1); - XFlush((Display*)fDisplay); + ClearWindowW((WinContext_t) gCws); } //////////////////////////////////////////////////////////////////////////////// -/// Clear current window. +/// Clear specified window. -void TGX11::ClearWindow() +void TGX11::ClearWindowW(WinContext_t wctxt) { - if (!gCws) return; + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - if (!gCws->fIsPixmap && !gCws->fDoubleBuffer) { - XSetWindowBackground((Display*)fDisplay, gCws->fDrawing, GetColor(0).fPixel); - XClearWindow((Display*)fDisplay, gCws->fDrawing); + if (!ctxt->fIsPixmap && !ctxt->fDoubleBuffer) { + XSetWindowBackground((Display*)fDisplay, ctxt->fDrawing, GetColor(0).fPixel); + XClearWindow((Display*)fDisplay, ctxt->fDrawing); XFlush((Display*)fDisplay); } else { - SetColor(gGCpxmp, 0); - XFillRectangle((Display*)fDisplay, gCws->fDrawing, *gGCpxmp, - 0, 0, gCws->fWidth, gCws->fHeight); - SetColor(gGCpxmp, 1); + SetColor(ctxt, &ctxt->fGClist[kGCpxmp], 0); + XFillRectangle((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCpxmp], + 0, 0, ctxt->fWidth, ctxt->fHeight); + SetColor(ctxt, &ctxt->fGClist[kGCpxmp], 1); } } @@ -439,7 +412,7 @@ void TGX11::ClearWindow() void TGX11::ClosePixmap() { - CloseWindow1(); + CloseWindow(); } //////////////////////////////////////////////////////////////////////////////// @@ -447,28 +420,8 @@ void TGX11::ClosePixmap() void TGX11::CloseWindow() { - if (gCws->fShared) - gCws->fOpen = 0; - else - CloseWindow1(); - - // Never close connection. TApplication takes care of that - // if (!gCws) Close(); // close X when no open window left -} - -//////////////////////////////////////////////////////////////////////////////// -/// Delete current window. - -void TGX11::CloseWindow1() -{ - int wid; - - if (gCws->fIsPixmap) - XFreePixmap((Display*)fDisplay, gCws->fWindow); - else - XDestroyWindow((Display*)fDisplay, gCws->fWindow); - - if (gCws->fBuffer) XFreePixmap((Display*)fDisplay, gCws->fBuffer); + if (gCws->fBuffer) + XFreePixmap((Display*)fDisplay, gCws->fBuffer); if (gCws->fNewColors) { if (fRedDiv == -1) @@ -477,18 +430,41 @@ void TGX11::CloseWindow1() gCws->fNewColors = nullptr; } - XFlush((Display*)fDisplay); + if (!gCws->fShared) { // if not QT window + if (gCws->fIsPixmap) + XFreePixmap((Display*)fDisplay, gCws->fWindow); + else + XDestroyWindow((Display*)fDisplay, gCws->fWindow); + + XFlush((Display*)fDisplay); + } + + for (int i = 0; i < kMAXGC; ++i) + XFreeGC((Display*)fDisplay, gCws->fGClist[i]); + + if (gCws->fillPattern != 0) { + XFreePixmap((Display*)fDisplay, gCws->fillPattern); + gCws->fillPattern = 0; + } gCws->fOpen = 0; - // make first window in list the current window - for (wid = 0; wid < fMaxNumberOfWindows; wid++) - if (fWindows[wid].fOpen) { - gCws = &fWindows[wid]; - return; + for (auto iter = fWindows.begin(); iter != fWindows.end(); ++iter) + if (iter->second.get() == gCws) { + fWindows.erase(iter); + gCws = nullptr; + break; } - gCws = nullptr; + if (gCws) + Fatal("CloseWindow", "Not found gCws in list of windows"); + + // select first from active windows + for (auto iter = fWindows.begin(); iter != fWindows.end(); ++iter) + if (iter->second && iter->second->fOpen) { + gCws = iter->second.get(); + return; + } } //////////////////////////////////////////////////////////////////////////////// @@ -496,35 +472,34 @@ void TGX11::CloseWindow1() void TGX11::CopyPixmap(int wid, int xpos, int ypos) { - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); - XCopyArea((Display*)fDisplay, gTws->fDrawing, gCws->fDrawing, *gGCpxmp, 0, 0, gTws->fWidth, + XCopyArea((Display*)fDisplay, gTws->fDrawing, gCws->fDrawing, gTws->fGClist[kGCpxmp], 0, 0, gTws->fWidth, gTws->fHeight, xpos, ypos); XFlush((Display*)fDisplay); } //////////////////////////////////////////////////////////////////////////////// -/// Copy area of current window in the pixmap pix. +/// Draw a box. +/// +/// - mode=0 hollow (kHollow) +/// - mode=1 solid (kSolid) -void TGX11::CopyWindowtoPixmap(Drawable *pix, int xpos, int ypos ) +void TGX11::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode) { - Window root; - int xx, yy; - unsigned int ww, hh, border, depth; - - XGetGeometry((Display*)fDisplay, *pix, &root, &xx, &yy, &ww, &hh, &border, &depth); - XCopyArea((Display*)fDisplay, gCws->fDrawing, *pix, *gGCpxmp, xpos, ypos, ww, hh, 0, 0); - XFlush((Display*)fDisplay); + DrawBoxW((WinContext_t) gCws, x1, y1, x2, y2, mode); } //////////////////////////////////////////////////////////////////////////////// -/// Draw a box. +/// Draw a box on specified window /// /// - mode=0 hollow (kHollow) /// - mode=1 solid (kSolid) -void TGX11::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode) +void TGX11::DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) { + auto ctxt = (XWindow_t *) wctxt; + Int_t x = TMath::Min(x1, x2); Int_t y = TMath::Min(y1, y2); Int_t w = TMath::Abs(x2 - x1); @@ -533,11 +508,11 @@ void TGX11::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode) switch (mode) { case kHollow: - XDrawRectangle((Display*)fDisplay, gCws->fDrawing, *gGCline, x, y, w, h); + XDrawRectangle((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCline], x, y, w, h); break; case kFilled: - XFillRectangle((Display*)fDisplay, gCws->fDrawing, *gGCfill, x, y, w, h); + XFillRectangle((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCfill], x, y, w, h); break; default: @@ -571,10 +546,10 @@ void TGX11::DrawCellArray(int x1, int y1, int x2, int y2, int nx, int ny, int *i for (j = 0; j < ny; j++) { icol = ic[i+(nx*j)]; if (icol != current_icol) { - XSetForeground((Display*)fDisplay, *gGCfill, GetColor(icol).fPixel); + XSetForeground((Display*)fDisplay, gCws->fGClist[kGCfill], GetColor(icol).fPixel); current_icol = icol; } - XFillRectangle((Display*)fDisplay, gCws->fDrawing, *gGCfill, ix, iy, w, h); + XFillRectangle((Display*)fDisplay, gCws->fDrawing, gCws->fGClist[kGCfill], ix, iy, w, h); iy = iy-h; } ix = ix+w; @@ -589,13 +564,25 @@ void TGX11::DrawCellArray(int x1, int y1, int x2, int y2, int nx, int ny, int *i void TGX11::DrawFillArea(int n, TPoint *xy) { - XPoint *xyp = (XPoint*)xy; + DrawFillAreaW((WinContext_t) gCws, n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Fill area described by polygon on specified window +/// +/// \param [in] n number of points +/// \param [in] xy list of points + +void TGX11::DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy) +{ + auto ctxt = (XWindow_t *) wctxt; + XPoint *xyp = (XPoint *)xy; - if (gFillHollow) - XDrawLines((Display*)fDisplay, gCws->fDrawing, *gGCfill, xyp, n, CoordModeOrigin); + if (ctxt->fillHollow) + XDrawLines((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCfill], xyp, n, CoordModeOrigin); else { - XFillPolygon((Display*)fDisplay, gCws->fDrawing, *gGCfill, + XFillPolygon((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCfill], xyp, n, Nonconvex, CoordModeOrigin); } } @@ -608,11 +595,24 @@ void TGX11::DrawFillArea(int n, TPoint *xy) void TGX11::DrawLine(Int_t x1, Int_t y1, Int_t x2, Int_t y2) { - if (gLineStyle == LineSolid) - XDrawLine((Display*)fDisplay, gCws->fDrawing, *gGCline, x1, y1, x2, y2); + DrawLineW((WinContext_t) gCws, x1, y1, x2, y2); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw a line on specified window. +/// +/// \param [in] x1,y1 : begin of line +/// \param [in] x2,y2 : end of line + +void TGX11::DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2) +{ + auto ctxt = (XWindow_t *) wctxt; + + if (ctxt->lineStyle == LineSolid) + XDrawLine((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCline], x1, y1, x2, y2); else { - XSetDashes((Display*)fDisplay, *gGCdash, gDashOffset, gDashList, gDashSize); - XDrawLine((Display*)fDisplay, gCws->fDrawing, *gGCdash, x1, y1, x2, y2); + XSetDashes((Display*)fDisplay, ctxt->fGClist[kGCdash], ctxt->dashOffset, ctxt->dashList.data(), ctxt->dashList.size()); + XDrawLine((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCdash], x1, y1, x2, y2); } } @@ -624,6 +624,18 @@ void TGX11::DrawLine(Int_t x1, Int_t y1, Int_t x2, Int_t y2) void TGX11::DrawPolyLine(int n, TPoint *xy) { + DrawPolyLineW((WinContext_t) gCws, n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw a line through all points on specified window. +/// +/// \param [in] n number of points +/// \param [in] xy list of points + +void TGX11::DrawPolyLineW(WinContext_t wctxt, Int_t n, TPoint *xy) +{ + auto ctxt = (XWindow_t *) wctxt; XPoint *xyp = (XPoint*)xy; const Int_t kMaxPoints = 1000001; @@ -632,39 +644,36 @@ void TGX11::DrawPolyLine(int n, TPoint *xy) int ibeg = 0; int iend = kMaxPoints - 1; while (iend < n) { - DrawPolyLine( kMaxPoints, &xy[ibeg] ); + DrawPolyLineW(wctxt, kMaxPoints, &xy[ibeg]); ibeg = iend; iend += kMaxPoints - 1; } if (ibeg < n) { int npt = n - ibeg; - DrawPolyLine( npt, &xy[ibeg] ); + DrawPolyLineW(wctxt, npt, &xy[ibeg]); } } else if (n > 1) { - if (gLineStyle == LineSolid) - XDrawLines((Display*)fDisplay, gCws->fDrawing, *gGCline, xyp, n, CoordModeOrigin); + if (ctxt->lineStyle == LineSolid) + XDrawLines((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCline], xyp, n, CoordModeOrigin); else { - int i; - XSetDashes((Display*)fDisplay, *gGCdash, - gDashOffset, gDashList, gDashSize); - XDrawLines((Display*)fDisplay, gCws->fDrawing, *gGCdash, xyp, n, CoordModeOrigin); + XSetDashes((Display*)fDisplay, ctxt->fGClist[kGCdash], ctxt->dashOffset, ctxt->dashList.data(), ctxt->dashList.size()); + XDrawLines((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCdash], xyp, n, CoordModeOrigin); // calculate length of line to update dash offset - for (i = 1; i < n; i++) { + for (int i = 1; i < n; i++) { int dx = xyp[i].x - xyp[i-1].x; int dy = xyp[i].y - xyp[i-1].y; if (dx < 0) dx = - dx; if (dy < 0) dy = - dy; - gDashOffset += dx > dy ? dx : dy; + ctxt->dashOffset += dx > dy ? dx : dy; } - gDashOffset %= gDashLength; + ctxt->dashOffset %= ctxt->dashLength; } } else { - int px,py; - px=xyp[0].x; - py=xyp[0].y; - XDrawPoint((Display*)fDisplay, gCws->fDrawing, - gLineStyle == LineSolid ? *gGCline : *gGCdash, px, py); + int px = xyp[0].x; + int py = xyp[0].y; + XDrawPoint((Display*)fDisplay, ctxt->fDrawing, + ctxt->lineStyle == LineSolid ? ctxt->fGClist[kGCline] : ctxt->fGClist[kGCdash], px, py); } } @@ -676,21 +685,34 @@ void TGX11::DrawPolyLine(int n, TPoint *xy) void TGX11::DrawLinesSegments(Int_t n, TPoint *xy) { + DrawLinesSegmentsW((WinContext_t) gCws, n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draws N segments between provided points on specified windows +/// +/// \param [in] n number of segements +/// \param [in] xy list of points, size 2*n + +void TGX11::DrawLinesSegmentsW(WinContext_t wctxt, Int_t n, TPoint *xy) +{ + auto ctxt = (XWindow_t *) wctxt; + const Int_t kMaxSegments = 500000; if (n > kMaxSegments) { Int_t ibeg = 0; Int_t iend = kMaxSegments; while (ibeg < n) { - DrawLinesSegments(iend - ibeg, &xy[ibeg*2]); + DrawLinesSegmentsW(wctxt, iend - ibeg, &xy[ibeg*2]); ibeg = iend; iend = TMath::Min(n, iend + kMaxSegments); } } else if (n > 0) { - if (gLineStyle == LineSolid) - XDrawSegments((Display*)fDisplay, gCws->fDrawing, *gGCline, (XSegment *) xy, n); + if (ctxt->lineStyle == LineSolid) + XDrawSegments((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCline], (XSegment *) xy, n); else { - XSetDashes((Display*)fDisplay, *gGCdash, gDashOffset, gDashList, gDashSize); - XDrawSegments((Display*)fDisplay, gCws->fDrawing, *gGCdash, (XSegment *) xy, n); + XSetDashes((Display*)fDisplay, ctxt->fGClist[kGCdash], ctxt->dashOffset, ctxt->dashList.data(), ctxt->dashList.size()); + XDrawSegments((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCdash], (XSegment *) xy, n); } } } @@ -704,63 +726,69 @@ void TGX11::DrawLinesSegments(Int_t n, TPoint *xy) void TGX11::DrawPolyMarker(int n, TPoint *xy) { - XPoint *xyp = (XPoint*)xy; + DrawPolyMarkerW((WinContext_t) gCws, n, xy); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw n markers with the current attributes at position x, y on specified window. +/// +/// \param [in] n number of markers to draw +/// \param [in] xy x,y coordinates of markers + +void TGX11::DrawPolyMarkerW(WinContext_t wctxt, Int_t n, TPoint *xy) +{ + auto ctxt = (XWindow_t *) wctxt; + XPoint *xyp = (XPoint *) xy; - if (gMarker.n <= 0) { + if ((ctxt->markerShape.size() == 0) && (ctxt->markerSize <= 0)) { const int kNMAX = 1000000; int nt = n/kNMAX; for (int it=0;it<=nt;it++) { if (it < nt) { - XDrawPoints((Display*)fDisplay, gCws->fDrawing, *gGCmark, &xyp[it*kNMAX], kNMAX, CoordModeOrigin); + XDrawPoints((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], &xyp[it*kNMAX], kNMAX, CoordModeOrigin); } else { - XDrawPoints((Display*)fDisplay, gCws->fDrawing, *gGCmark, &xyp[it*kNMAX], n-it*kNMAX, CoordModeOrigin); + XDrawPoints((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], &xyp[it*kNMAX], n-it*kNMAX, CoordModeOrigin); } } } else { - int r = gMarker.n / 2; - int m; - - for (m = 0; m < n; m++) { - int hollow = 0; - - switch (gMarker.type) { - int i; - - case 0: // hollow circle - XDrawArc((Display*)fDisplay, gCws->fDrawing, *gGCmark, - xyp[m].x - r, xyp[m].y - r, gMarker.n, gMarker.n, 0, 360*64); - break; - - case 1: // filled circle - XFillArc((Display*)fDisplay, gCws->fDrawing, *gGCmark, - xyp[m].x - r, xyp[m].y - r, gMarker.n, gMarker.n, 0, 360*64); - break; - - case 2: // hollow polygon - hollow = 1; - case 3: // filled polygon - for (i = 0; i < gMarker.n; i++) { - gMarker.xy[i].x += xyp[m].x; - gMarker.xy[i].y += xyp[m].y; - } - if (hollow) - XDrawLines((Display*)fDisplay, gCws->fDrawing, *gGCmark, - gMarker.xy, gMarker.n, CoordModeOrigin); - else - XFillPolygon((Display*)fDisplay, gCws->fDrawing, *gGCmark, - gMarker.xy, gMarker.n, Nonconvex, CoordModeOrigin); - for (i = 0; i < gMarker.n; i++) { - gMarker.xy[i].x -= xyp[m].x; - gMarker.xy[i].y -= xyp[m].y; - } - break; - - case 4: // segmented line - for (i = 0; i < gMarker.n; i += 2) - XDrawLine((Display*)fDisplay, gCws->fDrawing, *gGCmark, - xyp[m].x + gMarker.xy[i].x, xyp[m].y + gMarker.xy[i].y, - xyp[m].x + gMarker.xy[i+1].x, xyp[m].y + gMarker.xy[i+1].y); - break; + int r = ctxt->markerSize / 2; + auto &shape = ctxt->markerShape; + + for (int m = 0; m < n; m++) { + if (ctxt->markerType == 0) { + // hollow circle + XDrawArc((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], + xyp[m].x - r, xyp[m].y - r, ctxt->markerSize, ctxt->markerSize, 0, 360*64); + } else if (ctxt->markerType == 1) { + // filled circle + XFillArc((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], + xyp[m].x - r, xyp[m].y - r, ctxt->markerSize, ctxt->markerSize, 0, 360*64); + } else { + for (size_t i = 0; i < shape.size(); i++) { + shape[i].x += xyp[m].x; + shape[i].y += xyp[m].y; + } + switch(ctxt->markerType) { + case 2: + // hollow polygon + XDrawLines((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], + shape.data(), shape.size(), CoordModeOrigin); + break; + case 3: + // filled polygon + XFillPolygon((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], + shape.data(), shape.size(), Nonconvex, CoordModeOrigin); + break; + case 4: + // segmented line + XDrawSegments((Display*)fDisplay, ctxt->fDrawing, ctxt->fGClist[kGCmark], + (XSegment *) shape.data(), shape.size()/2); + break; + } + for (size_t i = 0; i < shape.size(); i++) { + shape[i].x -= xyp[m].x; + shape[i].y -= xyp[m].y; + } } } } @@ -780,20 +808,57 @@ void TGX11::DrawPolyMarker(int n, TPoint *xy) void TGX11::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) { - XRotSetMagnification(mgn); + DrawTextW((WinContext_t) gCws, x, y, angle, mgn, text, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw a text string using current font. +/// +/// \param [in] mode : drawing mode +/// - mode=0 : the background is not drawn (kClear) +/// - mode=1 : the background is drawn (kOpaque) +/// \param [in] x,y : text position +/// \param [in] angle : text angle +/// \param [in] mgn : magnification factor +/// \param [in] text : text string + +void TGX11::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, + const wchar_t *text, ETextMode mode) +{ + DrawTextW((WinContext_t) gCws, x, y, angle, mgn, text, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Draw a text string using current font on specified window. +/// +/// \param [in] mode : drawing mode +/// - mode=0 : the background is not drawn (kClear) +/// - mode=1 : the background is drawn (kOpaque) +/// \param [in] x,y : text position +/// \param [in] angle : text angle +/// \param [in] mgn : magnification factor +/// \param [in] text : text string + +void TGX11::DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const char *text, ETextMode mode) +{ + auto ctxt = (XWindow_t *) wctxt; - if (!text) return; + if (!text || !ctxt->textFont || ctxt->fAttText.GetTextSize() < 0) + return; + + XRotSetMagnification(mgn); switch (mode) { case kClear: - XRotDrawAlignedString((Display*)fDisplay, gTextFont, angle, - gCws->fDrawing, *gGCtext, x, y, (char*)text, fTextAlign); + XRotDrawAlignedString((Display*)fDisplay, ctxt->textFont, angle, + ctxt->fDrawing, ctxt->fGClist[kGCtext], x, y, (char*)text, (int) ctxt->textAlign); break; case kOpaque: - XRotDrawAlignedImageString((Display*)fDisplay, gTextFont, angle, - gCws->fDrawing, *gGCtext, x, y, (char*)text, fTextAlign); + XRotDrawAlignedImageString((Display*)fDisplay, ctxt->textFont, angle, + ctxt->fDrawing, ctxt->fGClist[kGCtext], x, y, (char*)text, (int) ctxt->textAlign); break; default: @@ -946,7 +1011,7 @@ XColor_t &TGX11::GetColor(Int_t cid) } //////////////////////////////////////////////////////////////////////////////// -/// Return current window pointer. Protected method used by TGX11TTF. +/// Return current window pointer. Window_t TGX11::GetCurrentWindow() const { @@ -963,7 +1028,50 @@ void *TGX11::GetGC(Int_t which) const Error("GetGC", "trying to get illegal GC (which = %d)", which); return nullptr; } - return &gGClist[which]; + if (!gCws) { + Error("GetGC", "No current window selected"); + return nullptr; + } + return &gCws->fGClist[which]; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return X11 window for specified window context. +/// Protected method used by TGX11TTF. + +Window_t TGX11::GetWindow(WinContext_t wctxt) const +{ + auto ctxt = (XWindow_t *) wctxt; + return (Window_t) (ctxt ? ctxt->fDrawing : 0); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return X11 Graphics Context for specified window context. +/// Protected method used by TGX11TTF. + +void *TGX11::GetGCW(WinContext_t wctxt, Int_t which) const +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) { + Error("GetGC", "No window context specified"); + return nullptr; + } + + if (which >= kMAXGC || which < 0) { + Error("GetGC", "trying to get illegal GC (which = %d)", which); + return nullptr; + } + return &ctxt->fGClist[which]; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return text align value for specified window context. +/// Protected method used by TGX11TTF. + +TGX11::EAlign TGX11::GetTextAlignW(WinContext_t wctxt) const +{ + auto ctxt = (XWindow_t *) wctxt; + return ctxt ? ctxt->textAlign : kAlignNone; } //////////////////////////////////////////////////////////////////////////////// @@ -971,7 +1079,7 @@ void *TGX11::GetGC(Int_t which) const Int_t TGX11::GetDoubleBuffer(int wid) { - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); if (!gTws->fOpen) return -1; else @@ -1001,7 +1109,7 @@ void TGX11::GetGeometry(int wid, int &x, int &y, unsigned int &w, unsigned int & unsigned int border, depth; unsigned int width, height; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); XGetGeometry((Display*)fDisplay, gTws->fWindow, &root, &x, &y, &width, &height, &border, &depth); XTranslateCoordinates((Display*)fDisplay, gTws->fWindow, fRootWin, @@ -1096,7 +1204,8 @@ void TGX11::GetTextExtent(UInt_t &w, UInt_t &h, char *mess) Window_t TGX11::GetWindowID(int wid) { - return (Window_t) fWindows[wid].fWindow; + if (fWindows.count(wid) == 0) return 0; + return (Window_t) fWindows[wid]->fWindow; } //////////////////////////////////////////////////////////////////////////////// @@ -1108,7 +1217,7 @@ Window_t TGX11::GetWindowID(int wid) void TGX11::MoveWindow(Int_t wid, Int_t x, Int_t y) { - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); if (!gTws->fOpen) return; XMoveWindow((Display*)fDisplay, gTws->fWindow, x, y); @@ -1141,23 +1250,6 @@ Int_t TGX11::OpenDisplay(void *disp) char vendor[132]; strlcpy(vendor, XServerVendor((Display*)fDisplay),132); - // Create primitives graphic contexts - for (i = 0; i < kMAXGC; i++) - gGClist[i] = XCreateGC((Display*)fDisplay, fVisRootWin, 0, nullptr); - - XGCValues values; - if (XGetGCValues((Display*)fDisplay, *gGCtext, GCForeground|GCBackground, &values)) { - XSetForeground((Display*)fDisplay, *gGCinvt, values.background); - XSetBackground((Display*)fDisplay, *gGCinvt, values.foreground); - } else { - Error("OpenDisplay", "cannot get GC values"); - } - - // Turn-off GraphicsExpose and NoExpose event reporting for the pixmap - // manipulation GC, this to prevent these events from being stacked up - // without ever being processed and thereby wasting a lot of memory. - XSetGraphicsExposures((Display*)fDisplay, *gGCpxmp, False); - // Create input echo graphic context XGCValues echov; echov.foreground = fBlackPixel; @@ -1264,6 +1356,60 @@ Int_t TGX11::OpenDisplay(void *disp) return 0; } + +//////////////////////////////////////////////////////////////////////////////// +/// Add new window handle +/// Only for private usage + +Int_t TGX11::AddWindowHandle() +{ + Int_t maxid = 0; + for (auto & pair : fWindows) { + if (!pair.second->fOpen) { + pair.second->fOpen = 1; + return pair.first; + } + if (pair.first > maxid) + maxid = pair.first; + } + + if (fWindows.size() == (size_t) maxid) { + // all ids are in use - just add maximal+1 + maxid++; + } else + for (int id = 1; id < maxid; id++) { + if (fWindows.count(id) == 0) { + maxid = id; + break; + } + } + + fWindows.emplace(maxid, std::make_unique()); + + auto ctxt = fWindows[maxid].get(); + ctxt->fOpen = 1; + ctxt->drawMode = TVirtualX::kCopy; + for (int n = 0; n < kMAXGC; ++n) + ctxt->fGClist[n] = XCreateGC((Display*)fDisplay, fVisRootWin, 0, nullptr); + + XGCValues values; + if (XGetGCValues((Display*)fDisplay, ctxt->fGClist[kGCtext], GCForeground|GCBackground, &values)) { + XSetForeground((Display*)fDisplay, ctxt->fGClist[kGCinvt], values.background); + XSetBackground((Display*)fDisplay, ctxt->fGClist[kGCinvt], values.foreground); + } else { + Error("AddWindowHandle", "cannot get GC values"); + } + + // Turn-off GraphicsExpose and NoExpose event reporting for the pixmap + // manipulation GC, this to prevent these events from being stacked up + // without ever being processed and thereby wasting a lot of memory. + XSetGraphicsExposures((Display*)fDisplay, ctxt->fGClist[kGCpxmp], False); + + return maxid; +} + + + //////////////////////////////////////////////////////////////////////////////// /// Open a new pixmap. /// @@ -1273,40 +1419,24 @@ Int_t TGX11::OpenPixmap(unsigned int w, unsigned int h) { Window root; unsigned int wval, hval; - int xx, yy, i, wid; + int xx, yy; unsigned int ww, hh, border, depth; wval = w; hval = h; // Select next free window number - -again: - for (wid = 0; wid < fMaxNumberOfWindows; wid++) - if (!fWindows[wid].fOpen) { - fWindows[wid].fOpen = 1; - gCws = &fWindows[wid]; - break; - } - - if (wid == fMaxNumberOfWindows) { - int newsize = fMaxNumberOfWindows + 10; - fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t), - fMaxNumberOfWindows*sizeof(XWindow_t)); - for (i = fMaxNumberOfWindows; i < newsize; i++) - fWindows[i].fOpen = 0; - fMaxNumberOfWindows = newsize; - goto again; - } + int wid = AddWindowHandle(); + gCws = fWindows[wid].get(); gCws->fWindow = XCreatePixmap((Display*)fDisplay, fRootWin, wval, hval, fDepth); XGetGeometry((Display*)fDisplay, gCws->fWindow, &root, &xx, &yy, &ww, &hh, &border, &depth); - for (i = 0; i < kMAXGC; i++) - XSetClipMask((Display*)fDisplay, gGClist[i], None); + for (int i = 0; i < kMAXGC; i++) + XSetClipMask((Display*)fDisplay, gCws->fGClist[i], None); - SetColor(gGCpxmp, 0); - XFillRectangle((Display*)fDisplay, gCws->fWindow, *gGCpxmp, 0, 0, ww, hh); - SetColor(gGCpxmp, 1); + SetColor(gCws, &gCws->fGClist[kGCpxmp], 0); + XFillRectangle((Display*)fDisplay, gCws->fWindow, gCws->fGClist[kGCpxmp], 0, 0, ww, hh); + SetColor(gCws, &gCws->fGClist[kGCpxmp], 1); // Initialise the window structure gCws->fDrawing = gCws->fWindow; @@ -1331,7 +1461,6 @@ Int_t TGX11::InitWindow(ULong_t win) { XSetWindowAttributes attributes; ULong_t attr_mask = 0; - int wid; int xval, yval; unsigned int wval, hval, border, depth; Window root; @@ -1342,24 +1471,9 @@ Int_t TGX11::InitWindow(ULong_t win) // Select next free window number -again: - for (wid = 0; wid < fMaxNumberOfWindows; wid++) - if (!fWindows[wid].fOpen) { - fWindows[wid].fOpen = 1; - fWindows[wid].fDoubleBuffer = 0; - gCws = &fWindows[wid]; - break; - } - - if (wid == fMaxNumberOfWindows) { - int newsize = fMaxNumberOfWindows + 10; - fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t), - fMaxNumberOfWindows*sizeof(XWindow_t)); - for (int i = fMaxNumberOfWindows; i < newsize; i++) - fWindows[i].fOpen = 0; - fMaxNumberOfWindows = newsize; - goto again; - } + int wid = AddWindowHandle(); + gCws = fWindows[wid].get(); + gCws->fDoubleBuffer = 0; // Create window @@ -1406,28 +1520,10 @@ Int_t TGX11::InitWindow(ULong_t win) Int_t TGX11::AddWindow(ULong_t qwid, UInt_t w, UInt_t h) { - Int_t wid; - // Select next free window number - -again: - for (wid = 0; wid < fMaxNumberOfWindows; wid++) - if (!fWindows[wid].fOpen) { - fWindows[wid].fOpen = 1; - fWindows[wid].fDoubleBuffer = 0; - gCws = &fWindows[wid]; - break; - } - - if (wid == fMaxNumberOfWindows) { - int newsize = fMaxNumberOfWindows + 10; - fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t), - fMaxNumberOfWindows*sizeof(XWindow_t)); - for (int i = fMaxNumberOfWindows; i < newsize; i++) - fWindows[i].fOpen = 0; - fMaxNumberOfWindows = newsize; - goto again; - } + int wid = AddWindowHandle(); + gCws = fWindows[wid].get(); + gCws->fDoubleBuffer = 0; gCws->fWindow = qwid; @@ -1446,32 +1542,14 @@ Int_t TGX11::AddWindow(ULong_t qwid, UInt_t w, UInt_t h) } //////////////////////////////////////////////////////////////////////////////// -/// Remove a window created by Qt (like CloseWindow1()). +/// Remove a window created by Qt (like CloseWindow()). void TGX11::RemoveWindow(ULong_t qwid) { - SelectWindow((int)qwid); + SelectWindow((int) qwid); - if (gCws->fBuffer) XFreePixmap((Display*)fDisplay, gCws->fBuffer); - - if (gCws->fNewColors) { - if (fRedDiv == -1) - XFreeColors((Display*)fDisplay, fColormap, gCws->fNewColors, gCws->fNcolors, 0); - delete [] gCws->fNewColors; - gCws->fNewColors = nullptr; - } - - gCws->fOpen = 0; - - // make first window in list the current window - for (Int_t wid = 0; wid < fMaxNumberOfWindows; wid++) - if (fWindows[wid].fOpen) { - gCws = &fWindows[wid]; - return; - } - - gCws = nullptr; -} + CloseWindow(); +} //////////////////////////////////////////////////////////////////////////////// /// Query pointer position. @@ -1495,13 +1573,6 @@ void TGX11::QueryPointer(Int_t &ix, Int_t &iy) iy = root_y_return; } -//////////////////////////////////////////////////////////////////////////////// -/// Remove the pixmap pix. - -void TGX11::RemovePixmap(Drawable *pix) -{ - XFreePixmap((Display*)fDisplay,*pix); -} //////////////////////////////////////////////////////////////////////////////// /// Request Locator position. @@ -1740,11 +1811,11 @@ Int_t TGX11::RequestString(int x, int y, char *text) char nbytes; int dx; int i; - XDrawImageString((Display*)fDisplay, gCws->fWindow, *gGCtext, x, y, text, nt); - dx = XTextWidth(gTextFont, text, nt); - XDrawImageString((Display*)fDisplay, gCws->fWindow, *gGCtext, x + dx, y, " ", 1); - dx = pt == 0 ? 0 : XTextWidth(gTextFont, text, pt); - XDrawImageString((Display*)fDisplay, gCws->fWindow, *gGCinvt, + XDrawImageString((Display*)fDisplay, gCws->fWindow, gCws->fGClist[kGCtext], x, y, text, nt); + dx = XTextWidth(gCws->textFont, text, nt); + XDrawImageString((Display*)fDisplay, gCws->fWindow, gCws->fGClist[kGCtext], x + dx, y, " ", 1); + dx = pt == 0 ? 0 : XTextWidth(gCws->textFont, text, pt); + XDrawImageString((Display*)fDisplay, gCws->fWindow, gCws->fGClist[kGCinvt], x + dx, y, pt < len_text ? &text[pt] : " ", 1); XWindowEvent((Display*)fDisplay, gCws->fWindow, gKeybdMask, &event); switch (event.type) { @@ -1869,9 +1940,7 @@ Int_t TGX11::RequestString(int x, int y, char *text) void TGX11::RescaleWindow(int wid, unsigned int w, unsigned int h) { - int i; - - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); if (!gTws->fOpen) return; // don't do anything when size did not change @@ -1885,11 +1954,13 @@ void TGX11::RescaleWindow(int wid, unsigned int w, unsigned int h) XFreePixmap((Display*)fDisplay,gTws->fBuffer); gTws->fBuffer = XCreatePixmap((Display*)fDisplay, fRootWin, w, h, fDepth); } - for (i = 0; i < kMAXGC; i++) XSetClipMask((Display*)fDisplay, gGClist[i], None); - SetColor(gGCpxmp, 0); - XFillRectangle( (Display*)fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, w, h); - SetColor(gGCpxmp, 1); - if (gTws->fDoubleBuffer) gTws->fDrawing = gTws->fBuffer; + for (int i = 0; i < kMAXGC; i++) + XSetClipMask((Display*)fDisplay, gTws->fGClist[i], None); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 0); + XFillRectangle((Display*)fDisplay, gTws->fBuffer, gTws->fGClist[kGCpxmp], 0, 0, w, h); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 1); + if (gTws->fDoubleBuffer) + gTws->fDrawing = gTws->fBuffer; } gTws->fWidth = w; gTws->fHeight = h; @@ -1910,7 +1981,7 @@ int TGX11::ResizePixmap(int wid, unsigned int w, unsigned int h) wval = w; hval = h; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); // don't do anything when size did not change // if (gTws->fWidth == wval && gTws->fHeight == hval) return 0; @@ -1928,11 +1999,11 @@ int TGX11::ResizePixmap(int wid, unsigned int w, unsigned int h) XGetGeometry((Display*)fDisplay, gTws->fWindow, &root, &xx, &yy, &ww, &hh, &border, &depth); for (i = 0; i < kMAXGC; i++) - XSetClipMask((Display*)fDisplay, gGClist[i], None); + XSetClipMask((Display*)fDisplay, gTws->fGClist[i], None); - SetColor(gGCpxmp, 0); - XFillRectangle((Display*)fDisplay, gTws->fWindow, *gGCpxmp, 0, 0, ww, hh); - SetColor(gGCpxmp, 1); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 0); + XFillRectangle((Display*)fDisplay, gTws->fWindow, gTws->fGClist[kGCpxmp], 0, 0, ww, hh); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 1); // Initialise the window structure gTws->fDrawing = gTws->fWindow; @@ -1947,12 +2018,11 @@ int TGX11::ResizePixmap(int wid, unsigned int w, unsigned int h) void TGX11::ResizeWindow(Int_t wid) { - int i; int xval=0, yval=0; Window win, root=0; unsigned int wval=0, hval=0, border=0, depth=0; - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); win = gTws->fWindow; @@ -1971,11 +2041,13 @@ void TGX11::ResizeWindow(Int_t wid) XFreePixmap((Display*)fDisplay,gTws->fBuffer); gTws->fBuffer = XCreatePixmap((Display*)fDisplay, fRootWin, wval, hval, fDepth); } - for (i = 0; i < kMAXGC; i++) XSetClipMask((Display*)fDisplay, gGClist[i], None); - SetColor(gGCpxmp, 0); - XFillRectangle((Display*)fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, wval, hval); - SetColor(gGCpxmp, 1); - if (gTws->fDoubleBuffer) gTws->fDrawing = gTws->fBuffer; + for (int i = 0; i < kMAXGC; i++) + XSetClipMask((Display*)fDisplay, gTws->fGClist[i], None); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 0); + XFillRectangle((Display*)fDisplay, gTws->fBuffer, gTws->fGClist[kGCpxmp], 0, 0, wval, hval); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 1); + if (gTws->fDoubleBuffer) + gTws->fDrawing = gTws->fBuffer; } gTws->fWidth = wval; gTws->fHeight = hval; @@ -1986,23 +2058,25 @@ void TGX11::ResizeWindow(Int_t wid) void TGX11::SelectWindow(int wid) { - XRectangle region; - int i; + if ((wid == 0) || (fWindows.count(wid) == 0)) + return; - if (wid < 0 || wid >= fMaxNumberOfWindows || !fWindows[wid].fOpen) return; + if (!fWindows[wid]->fOpen) + return; - gCws = &fWindows[wid]; + gCws = fWindows[wid].get(); if (gCws->fClip && !gCws->fIsPixmap && !gCws->fDoubleBuffer) { + XRectangle region; region.x = gCws->fXclip; region.y = gCws->fYclip; region.width = gCws->fWclip; region.height = gCws->fHclip; - for (i = 0; i < kMAXGC; i++) - XSetClipRectangles((Display*)fDisplay, gGClist[i], 0, 0, ®ion, 1, YXBanded); + for (int i = 0; i < kMAXGC; i++) + XSetClipRectangles((Display*)fDisplay, gCws->fGClist[i], 0, 0, ®ion, 1, YXBanded); } else { - for (i = 0; i < kMAXGC; i++) - XSetClipMask((Display*)fDisplay, gGClist[i], None); + for (int i = 0; i < kMAXGC; i++) + XSetClipMask((Display*)fDisplay, gCws->fGClist[i], None); } } @@ -2032,11 +2106,11 @@ void TGX11::SetCharacterUp(Float_t chupx, Float_t chupy) void TGX11::SetClipOFF(int wid) { - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); gTws->fClip = 0; for (int i = 0; i < kMAXGC; i++) - XSetClipMask( (Display*)fDisplay, gGClist[i], None ); + XSetClipMask( (Display*)fDisplay, gTws->fGClist[i], None ); } //////////////////////////////////////////////////////////////////////////////// @@ -2048,8 +2122,7 @@ void TGX11::SetClipOFF(int wid) void TGX11::SetClipRegion(int wid, int x, int y, unsigned int w, unsigned int h) { - - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); gTws->fXclip = x; gTws->fYclip = y; gTws->fWclip = w; @@ -2062,14 +2135,14 @@ void TGX11::SetClipRegion(int wid, int x, int y, unsigned int w, unsigned int h) region.width = gTws->fWclip; region.height = gTws->fHclip; for (int i = 0; i < kMAXGC; i++) - XSetClipRectangles((Display*)fDisplay, gGClist[i], 0, 0, ®ion, 1, YXBanded); + XSetClipRectangles((Display*)fDisplay, gTws->fGClist[i], 0, 0, ®ion, 1, YXBanded); } } //////////////////////////////////////////////////////////////////////////////// /// Set the foreground color in GC. -void TGX11::SetColor(void *gci, int ci) +void TGX11::SetColor(XWindow_t *ctxt, void *gci, int ci) { GC gc = *(GC *)gci; @@ -2084,7 +2157,7 @@ void TGX11::SetColor(void *gci, int ci) col = GetColor(0); } - if (fDrawMode == kXor) { + if (ctxt && ctxt->drawMode == kXor) { XGCValues values; XGetGCValues((Display*)fDisplay, gc, GCBackground, &values); XSetForeground((Display*)fDisplay, gc, col.fPixel ^ values.background); @@ -2104,7 +2177,7 @@ void TGX11::SetColor(void *gci, int ci) void TGX11::SetCursor(Int_t wid, ECursor cursor) { - gTws = &fWindows[wid]; + gTws = fWindows[wid].get(); XDefineCursor((Display*)fDisplay, gTws->fWindow, fCursors[cursor]); } @@ -2120,8 +2193,8 @@ void TGX11::SetCursor(Int_t wid, ECursor cursor) void TGX11::SetDoubleBuffer(int wid, int mode) { if (wid == 999) { - for (int i = 0; i < fMaxNumberOfWindows; i++) { - gTws = &fWindows[i]; + for (auto & pair : fWindows) { + gTws = pair.second.get(); if (gTws->fOpen) { switch (mode) { case 1 : @@ -2134,8 +2207,9 @@ void TGX11::SetDoubleBuffer(int wid, int mode) } } } else { - gTws = &fWindows[wid]; - if (!gTws->fOpen) return; + gTws = fWindows[wid].get(); + if (!gTws->fOpen) + return; switch (mode) { case 1 : SetDoubleBufferON(); @@ -2162,15 +2236,17 @@ void TGX11::SetDoubleBufferOFF() void TGX11::SetDoubleBufferON() { - if (gTws->fDoubleBuffer || gTws->fIsPixmap) return; + if (gTws->fDoubleBuffer || gTws->fIsPixmap) + return; if (!gTws->fBuffer) { gTws->fBuffer = XCreatePixmap((Display*)fDisplay, fRootWin, gTws->fWidth, gTws->fHeight, fDepth); - SetColor(gGCpxmp, 0); - XFillRectangle((Display*)fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, gTws->fWidth, gTws->fHeight); - SetColor(gGCpxmp, 1); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 0); + XFillRectangle((Display*)fDisplay, gTws->fBuffer, gTws->fGClist[kGCpxmp], 0, 0, gTws->fWidth, gTws->fHeight); + SetColor(gTws, &gTws->fGClist[kGCpxmp], 1); } - for (int i = 0; i < kMAXGC; i++) XSetClipMask((Display*)fDisplay, gGClist[i], None); + for (int i = 0; i < kMAXGC; i++) + XSetClipMask((Display*)fDisplay, gTws->fGClist[i], None); gTws->fDoubleBuffer = 1; gTws->fDrawing = gTws->fBuffer; } @@ -2187,23 +2263,7 @@ void TGX11::SetDoubleBufferON() void TGX11::SetDrawMode(EDrawMode mode) { - int i; - if (fDisplay) { - switch (mode) { - case kCopy: - for (i = 0; i < kMAXGC; i++) XSetFunction((Display*)fDisplay, gGClist[i], GXcopy); - break; - - case kXor: - for (i = 0; i < kMAXGC; i++) XSetFunction((Display*)fDisplay, gGClist[i], GXxor); - break; - - case kInvert: - for (i = 0; i < kMAXGC; i++) XSetFunction((Display*)fDisplay, gGClist[i], GXinvert); - break; - } - } - fDrawMode = mode; + SetDrawModeW((WinContext_t) gCws, mode); } //////////////////////////////////////////////////////////////////////////////// @@ -2211,15 +2271,14 @@ void TGX11::SetDrawMode(EDrawMode mode) void TGX11::SetFillColor(Color_t cindex) { - if (!gStyle->GetFillColor() && cindex > 1) cindex = 0; - if (cindex >= 0) SetColor(gGCfill, Int_t(cindex)); - fFillColor = cindex; + if (cindex < 0) return; - // invalidate fill pattern - if (gFillPattern != 0) { - XFreePixmap((Display*)fDisplay, gFillPattern); - gFillPattern = 0; - } + TAttFill::SetFillColor(cindex); + + TAttFill arg(gCws->fAttFill); + arg.SetFillColor(cindex); + + SetAttFill((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -2230,54 +2289,21 @@ void TGX11::SetFillColor(Color_t cindex) void TGX11::SetFillStyle(Style_t fstyle) { - if (fFillStyle == fstyle) return; - fFillStyle = fstyle; - Int_t style = fstyle/1000; - Int_t fasi = fstyle%1000; - SetFillStyleIndex(style,fasi); + TAttFill::SetFillStyle(fstyle); + + TAttFill arg(gCws->fAttFill); + arg.SetFillStyle(fstyle); + + SetAttFill((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// Set fill area style index. +/// Return current fill style +/// FIXME: Only as temporary solution while some code analyze current fill style -void TGX11::SetFillStyleIndex(Int_t style, Int_t fasi) +Style_t TGX11::GetFillStyle() const { - static int current_fasi = 0; - - fFillStyle = 1000*style + fasi; - - switch (style) { - - case 1: // solid - gFillHollow = 0; - XSetFillStyle((Display*)fDisplay, *gGCfill, FillSolid); - break; - - case 2: // pattern - gFillHollow = 1; - break; - - case 3: // hatch - gFillHollow = 0; - XSetFillStyle((Display*)fDisplay, *gGCfill, FillStippled); - if (fasi != current_fasi) { - if (gFillPattern != 0) { - XFreePixmap((Display*)fDisplay, gFillPattern); - gFillPattern = 0; - } - int stn = (fasi >= 1 && fasi <=25) ? fasi : 2; - - gFillPattern = XCreateBitmapFromData((Display*)fDisplay, fRootWin, - (const char*)gStipples[stn], 16, 16); - - XSetStipple( (Display*)fDisplay, *gGCfill, gFillPattern ); - current_fasi = fasi; - } - break; - - default: - gFillHollow = 1; - } + return gCws ? gCws->fAttFill.GetFillStyle() : TAttFill::GetFillStyle(); } //////////////////////////////////////////////////////////////////////////////// @@ -2308,8 +2334,10 @@ void TGX11::SetLineColor(Color_t cindex) TAttLine::SetLineColor(cindex); - SetColor(gGCline, Int_t(cindex)); - SetColor(gGCdash, Int_t(cindex)); + TAttLine arg(gCws->fAttLine); + arg.SetLineColor(cindex); + + SetAttLine((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -2323,27 +2351,9 @@ void TGX11::SetLineColor(Color_t cindex) /// e.g. N=4,DASH=(6,3,1,3) gives a dashed-dotted line with dash length 6 /// and a gap of 7 between dashes -void TGX11::SetLineType(int n, int *dash) +void TGX11::SetLineType(int /* n */, int * /* dash */) { - if (n <= 0) { - gLineStyle = LineSolid; - XSetLineAttributes((Display*)fDisplay, *gGCline, gLineWidth, - gLineStyle, gCapStyle, gJoinStyle); - } else { - gDashSize = TMath::Min((int)sizeof(gDashList),n); - gDashLength = 0; - for (int i = 0; i < gDashSize; i++ ) { - gDashList[i] = dash[i]; - gDashLength += gDashList[i]; - } - gDashOffset = 0; - gLineStyle = LineOnOffDash; - if (gLineWidth == 0) gLineWidth =1; - XSetLineAttributes((Display*)fDisplay, *gGCline, gLineWidth, - gLineStyle, gCapStyle, gJoinStyle); - XSetLineAttributes((Display*)fDisplay, *gGCdash, gLineWidth, - gLineStyle, gCapStyle, gJoinStyle); - } + Warning("SetLineType", "DEPRECATED, use SetAttLine() instead"); } //////////////////////////////////////////////////////////////////////////////// @@ -2351,36 +2361,21 @@ void TGX11::SetLineType(int n, int *dash) void TGX11::SetLineStyle(Style_t lstyle) { - static Int_t dashed[2] = {3,3}; - static Int_t dotted[2] = {1,2}; - static Int_t dasheddotted[4] = {3,4,1,4}; - - if (fLineStyle != lstyle) { //set style index only if different - fLineStyle = lstyle; - if (lstyle <= 1 ) { - SetLineType(0, nullptr); - } else if (lstyle == 2 ) { - SetLineType(2, dashed); - } else if (lstyle == 3 ) { - SetLineType(2, dotted); - } else if (lstyle == 4 ) { - SetLineType(4, dasheddotted); - } else { - TString st = (TString)gStyle->GetLineStyleString(lstyle); - TObjArray *tokens = st.Tokenize(" "); - Int_t nt; - nt = tokens->GetEntries(); - Int_t *linestyle = new Int_t[nt]; - for (Int_t j = 0; jAt(j))->GetName(), "%d", &it); - linestyle[j] = (Int_t)(it/4); - } - SetLineType(nt, linestyle); - delete [] linestyle; - delete tokens; - } - } + TAttLine::SetLineStyle(lstyle); + + TAttLine arg(gCws->fAttLine); + arg.SetLineStyle(lstyle); + + SetAttLine((WinContext_t) gCws, arg); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return current line style +/// FIXME: Only as temporary solution while some code analyze current line style + +Style_t TGX11::GetLineStyle() const +{ + return gCws ? gCws->fAttLine.GetLineStyle() : TAttLine::GetLineStyle(); } //////////////////////////////////////////////////////////////////////////////// @@ -2388,20 +2383,23 @@ void TGX11::SetLineStyle(Style_t lstyle) /// /// \param [in] width : line width in pixels -void TGX11::SetLineWidth(Width_t width ) +void TGX11::SetLineWidth(Width_t width) { - if (fLineWidth == width) return; - fLineWidth = width; + TAttLine::SetLineWidth(width); + + TAttLine arg(gCws->fAttLine); + arg.SetLineWidth(width); - if (width == 1 && gLineStyle == LineSolid) gLineWidth = 0; - else gLineWidth = width; + SetAttLine((WinContext_t) gCws, arg); +} - if (gLineWidth < 0) return; +//////////////////////////////////////////////////////////////////////////////// +/// Return current line width +/// FIXME: Only as temporary solution while some code analyze current line wide - XSetLineAttributes((Display*)fDisplay, *gGCline, gLineWidth, - gLineStyle, gCapStyle, gJoinStyle); - XSetLineAttributes((Display*)fDisplay, *gGCdash, gLineWidth, - gLineStyle, gCapStyle, gJoinStyle); +Width_t TGX11::GetLineWidth() const +{ + return gCws ? gCws->fAttLine.GetLineWidth() : TAttLine::GetLineWidth(); } //////////////////////////////////////////////////////////////////////////////// @@ -2413,7 +2411,10 @@ void TGX11::SetMarkerColor(Color_t cindex) TAttMarker::SetMarkerColor(cindex); - SetColor(gGCmark, Int_t(cindex)); + TAttMarker arg(gCws->fAttMarker); + arg.SetMarkerColor(cindex); + + SetAttMarker((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// @@ -2423,587 +2424,474 @@ void TGX11::SetMarkerColor(Color_t cindex) void TGX11::SetMarkerSize(Float_t msize) { - if (msize == fMarkerSize) return; + TAttMarker::SetMarkerSize(msize); - fMarkerSize = msize; - if (msize < 0) return; + TAttMarker arg(gCws->fAttMarker); + arg.SetMarkerSize(msize); - SetMarkerStyle(-fMarkerStyle); + SetAttMarker((WinContext_t) gCws, arg); } //////////////////////////////////////////////////////////////////////////////// -/// Set marker type. -/// -/// \param [in] type : marker type -/// \param [in] n : length of marker description -/// \param [in] xy : list of points describing marker shape -/// -/// - if n == 0 marker is a single point -/// - if TYPE == 0 marker is hollow circle of diameter N -/// - if TYPE == 1 marker is filled circle of diameter N -/// - if TYPE == 2 marker is a hollow polygon describe by line XY -/// - if TYPE == 3 marker is a filled polygon describe by line XY -/// - if TYPE == 4 marker is described by segmented line XY -/// e.g. TYPE=4,N=4,XY=(-3,0,3,0,0,-3,0,3) sets a plus shape of 7x7 pixels - -void TGX11::SetMarkerType(int type, int n, RXPoint *xy) -{ - gMarker.type = type; - gMarker.n = n < kMAXMK ? n : kMAXMK; - if (gMarker.type >= 2) { - for (int i = 0; i < gMarker.n; i++) { - gMarker.xy[i].x = xy[i].x; - gMarker.xy[i].y = xy[i].y; +/// Set marker style. + +void TGX11::SetMarkerStyle(Style_t markerstyle) +{ + TAttMarker::SetMarkerStyle(markerstyle); + + TAttMarker arg(gCws->fAttMarker); + arg.SetMarkerStyle(markerstyle); + + SetAttMarker((WinContext_t) gCws, arg); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set opacity of a window. This image manipulation routine works +/// by adding to a percent amount of neutral to each pixels RGB. +/// Since it requires quite some additional color map entries is it +/// only supported on displays with more than > 8 color planes (> 256 +/// colors). + +void TGX11::SetOpacity(Int_t percent) +{ + if (fDepth <= 8) return; + if (percent == 0) return; + // if 100 percent then just make white + + ULong_t *orgcolors = nullptr, *tmpc = nullptr; + Int_t maxcolors = 0, ncolors = 0, ntmpc = 0; + + // save previous allocated colors, delete at end when not used anymore + if (gCws->fNewColors) { + tmpc = gCws->fNewColors; + ntmpc = gCws->fNcolors; + } + + // get pixmap from server as image + XImage *image = XGetImage((Display*)fDisplay, gCws->fDrawing, 0, 0, gCws->fWidth, + gCws->fHeight, AllPlanes, ZPixmap); + if (!image) return; + // collect different image colors + int x, y; + for (y = 0; y < (int) gCws->fHeight; y++) { + for (x = 0; x < (int) gCws->fWidth; x++) { + ULong_t pixel = XGetPixel(image, x, y); + CollectImageColors(pixel, orgcolors, ncolors, maxcolors); + } + } + if (ncolors == 0) { + XDestroyImage(image); + ::operator delete(orgcolors); + return; + } + + // create opaque counter parts + MakeOpaqueColors(percent, orgcolors, ncolors); + + if (gCws->fNewColors) { + // put opaque colors in image + for (y = 0; y < (int) gCws->fHeight; y++) { + for (x = 0; x < (int) gCws->fWidth; x++) { + ULong_t pixel = XGetPixel(image, x, y); + Int_t idx = FindColor(pixel, orgcolors, ncolors); + XPutPixel(image, x, y, gCws->fNewColors[idx]); + } } } + + // put image back in pixmap on server + XPutImage((Display*)fDisplay, gCws->fDrawing, gCws->fGClist[kGCpxmp], image, 0, 0, 0, 0, + gCws->fWidth, gCws->fHeight); + XFlush((Display*)fDisplay); + + // clean up + if (tmpc) { + if (fRedDiv == -1) + XFreeColors((Display*)fDisplay, fColormap, tmpc, ntmpc, 0); + delete [] tmpc; + } + XDestroyImage(image); + ::operator delete(orgcolors); } //////////////////////////////////////////////////////////////////////////////// -/// Set marker style. +/// Collect in orgcolors all different original image colors. -void TGX11::SetMarkerStyle(Style_t markerstyle) +void TGX11::CollectImageColors(ULong_t pixel, ULong_t *&orgcolors, Int_t &ncolors, + Int_t &maxcolors) { - if (fMarkerStyle == markerstyle) return; - static RXPoint shape[30]; - fMarkerStyle = TMath::Abs(markerstyle); - markerstyle = TAttMarker::GetMarkerStyleBase(fMarkerStyle); - gMarkerLineWidth = TAttMarker::GetMarkerLineWidth(fMarkerStyle); + if (maxcolors == 0) { + ncolors = 0; + maxcolors = 100; + orgcolors = (ULong_t*) ::operator new(maxcolors*sizeof(ULong_t)); + } - // The fast pixel markers need to be treated separately - if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) { - XSetLineAttributes((Display*)fDisplay, *gGCmark, 0, LineSolid, CapButt, JoinMiter); - } else { - XSetLineAttributes((Display*)fDisplay, *gGCmark, gMarkerLineWidth, - gMarkerLineStyle, gMarkerCapStyle, gMarkerJoinStyle); + for (int i = 0; i < ncolors; i++) + if (pixel == orgcolors[i]) return; + + if (ncolors >= maxcolors) { + orgcolors = (ULong_t*) TStorage::ReAlloc(orgcolors, + maxcolors*2*sizeof(ULong_t), maxcolors*sizeof(ULong_t)); + maxcolors *= 2; } - Float_t MarkerSizeReduced = fMarkerSize - TMath::Floor(gMarkerLineWidth/2.)/4.; - Int_t im = Int_t(4*MarkerSizeReduced + 0.5); - if (markerstyle == 2) { - // + shaped marker - shape[0].x = -im; shape[0].y = 0; - shape[1].x = im; shape[1].y = 0; - shape[2].x = 0 ; shape[2].y = -im; - shape[3].x = 0 ; shape[3].y = im; - SetMarkerType(4,4,shape); - } else if (markerstyle == 3 || markerstyle == 31) { - // * shaped marker - shape[0].x = -im; shape[0].y = 0; - shape[1].x = im; shape[1].y = 0; - shape[2].x = 0 ; shape[2].y = -im; - shape[3].x = 0 ; shape[3].y = im; - im = Int_t(0.707*Float_t(im) + 0.5); - shape[4].x = -im; shape[4].y = -im; - shape[5].x = im; shape[5].y = im; - shape[6].x = -im; shape[6].y = im; - shape[7].x = im; shape[7].y = -im; - SetMarkerType(4,8,shape); - } else if (markerstyle == 4 || markerstyle == 24) { - // O shaped marker - SetMarkerType(0,im*2,shape); - } else if (markerstyle == 5) { - // X shaped marker - im = Int_t(0.707*Float_t(im) + 0.5); - shape[0].x = -im; shape[0].y = -im; - shape[1].x = im; shape[1].y = im; - shape[2].x = -im; shape[2].y = im; - shape[3].x = im; shape[3].y = -im; - SetMarkerType(4,4,shape); - } else if (markerstyle == 6) { - // + shaped marker (with 1 pixel) - shape[0].x = -1 ; shape[0].y = 0; - shape[1].x = 1 ; shape[1].y = 0; - shape[2].x = 0 ; shape[2].y = -1; - shape[3].x = 0 ; shape[3].y = 1; - SetMarkerType(4,4,shape); - } else if (markerstyle == 7) { - // . shaped marker (with 9 pixel) - shape[0].x = -1 ; shape[0].y = 1; - shape[1].x = 1 ; shape[1].y = 1; - shape[2].x = -1 ; shape[2].y = 0; - shape[3].x = 1 ; shape[3].y = 0; - shape[4].x = -1 ; shape[4].y = -1; - shape[5].x = 1 ; shape[5].y = -1; - SetMarkerType(4,6,shape); - } else if (markerstyle == 8 || markerstyle == 20) { - // O shaped marker (filled) - SetMarkerType(1,im*2,shape); - } else if (markerstyle == 21) { - // full square - shape[0].x = -im; shape[0].y = -im; - shape[1].x = im; shape[1].y = -im; - shape[2].x = im; shape[2].y = im; - shape[3].x = -im; shape[3].y = im; - shape[4].x = -im; shape[4].y = -im; - SetMarkerType(3,5,shape); - } else if (markerstyle == 22) { - // full triangle up - shape[0].x = -im; shape[0].y = im; - shape[1].x = im; shape[1].y = im; - shape[2].x = 0; shape[2].y = -im; - shape[3].x = -im; shape[3].y = im; - SetMarkerType(3,4,shape); - } else if (markerstyle == 23) { - // full triangle down - shape[0].x = 0; shape[0].y = im; - shape[1].x = im; shape[1].y = -im; - shape[2].x = -im; shape[2].y = -im; - shape[3].x = 0; shape[3].y = im; - SetMarkerType(3,4,shape); - } else if (markerstyle == 25) { - // open square - shape[0].x = -im; shape[0].y = -im; - shape[1].x = im; shape[1].y = -im; - shape[2].x = im; shape[2].y = im; - shape[3].x = -im; shape[3].y = im; - shape[4].x = -im; shape[4].y = -im; - SetMarkerType(2,5,shape); - } else if (markerstyle == 26) { - // open triangle up - shape[0].x = -im; shape[0].y = im; - shape[1].x = im; shape[1].y = im; - shape[2].x = 0; shape[2].y = -im; - shape[3].x = -im; shape[3].y = im; - SetMarkerType(2,4,shape); - } else if (markerstyle == 27) { - // open losange - Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5); - shape[0].x =-imx; shape[0].y = 0; - shape[1].x = 0; shape[1].y = -im; - shape[2].x = imx; shape[2].y = 0; - shape[3].x = 0; shape[3].y = im; - shape[4].x =-imx; shape[4].y = 0; - SetMarkerType(2,5,shape); - } else if (markerstyle == 28) { - // open cross - Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); - shape[0].x = -im; shape[0].y =-imx; - shape[1].x =-imx; shape[1].y =-imx; - shape[2].x =-imx; shape[2].y = -im; - shape[3].x = imx; shape[3].y = -im; - shape[4].x = imx; shape[4].y =-imx; - shape[5].x = im; shape[5].y =-imx; - shape[6].x = im; shape[6].y = imx; - shape[7].x = imx; shape[7].y = imx; - shape[8].x = imx; shape[8].y = im; - shape[9].x =-imx; shape[9].y = im; - shape[10].x=-imx; shape[10].y= imx; - shape[11].x= -im; shape[11].y= imx; - shape[12].x= -im; shape[12].y=-imx; - SetMarkerType(2,13,shape); - } else if (markerstyle == 29) { - // full star pentagone - Int_t im1 = Int_t(0.66*MarkerSizeReduced + 0.5); - Int_t im2 = Int_t(2.00*MarkerSizeReduced + 0.5); - Int_t im3 = Int_t(2.66*MarkerSizeReduced + 0.5); - Int_t im4 = Int_t(1.33*MarkerSizeReduced + 0.5); - shape[0].x = -im; shape[0].y = im4; - shape[1].x =-im2; shape[1].y =-im1; - shape[2].x =-im3; shape[2].y = -im; - shape[3].x = 0; shape[3].y =-im2; - shape[4].x = im3; shape[4].y = -im; - shape[5].x = im2; shape[5].y =-im1; - shape[6].x = im; shape[6].y = im4; - shape[7].x = im4; shape[7].y = im4; - shape[8].x = 0; shape[8].y = im; - shape[9].x =-im4; shape[9].y = im4; - shape[10].x= -im; shape[10].y= im4; - SetMarkerType(3,11,shape); - } else if (markerstyle == 30) { - // open star pentagone - Int_t im1 = Int_t(0.66*MarkerSizeReduced + 0.5); - Int_t im2 = Int_t(2.00*MarkerSizeReduced + 0.5); - Int_t im3 = Int_t(2.66*MarkerSizeReduced + 0.5); - Int_t im4 = Int_t(1.33*MarkerSizeReduced + 0.5); - shape[0].x = -im; shape[0].y = im4; - shape[1].x =-im2; shape[1].y =-im1; - shape[2].x =-im3; shape[2].y = -im; - shape[3].x = 0; shape[3].y =-im2; - shape[4].x = im3; shape[4].y = -im; - shape[5].x = im2; shape[5].y =-im1; - shape[6].x = im; shape[6].y = im4; - shape[7].x = im4; shape[7].y = im4; - shape[8].x = 0; shape[8].y = im; - shape[9].x =-im4; shape[9].y = im4; - shape[10].x= -im; shape[10].y= im4; - SetMarkerType(2,11,shape); - } else if (markerstyle == 32) { - // open triangle down - shape[0].x = 0; shape[0].y = im; - shape[1].x = im; shape[1].y = -im; - shape[2].x = -im; shape[2].y = -im; - shape[3].x = 0; shape[3].y = im; - SetMarkerType(2,4,shape); - } else if (markerstyle == 33) { - // full losange - Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5); - shape[0].x =-imx; shape[0].y = 0; - shape[1].x = 0; shape[1].y = -im; - shape[2].x = imx; shape[2].y = 0; - shape[3].x = 0; shape[3].y = im; - shape[4].x =-imx; shape[4].y = 0; - SetMarkerType(3,5,shape); - } else if (markerstyle == 34) { - // full cross - Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); - shape[0].x = -im; shape[0].y =-imx; - shape[1].x =-imx; shape[1].y =-imx; - shape[2].x =-imx; shape[2].y = -im; - shape[3].x = imx; shape[3].y = -im; - shape[4].x = imx; shape[4].y =-imx; - shape[5].x = im; shape[5].y =-imx; - shape[6].x = im; shape[6].y = imx; - shape[7].x = imx; shape[7].y = imx; - shape[8].x = imx; shape[8].y = im; - shape[9].x =-imx; shape[9].y = im; - shape[10].x=-imx; shape[10].y= imx; - shape[11].x= -im; shape[11].y= imx; - shape[12].x= -im; shape[12].y=-imx; - SetMarkerType(3,13,shape); - } else if (markerstyle == 35) { - // diamond with cross - shape[0].x =-im; shape[0].y = 0; - shape[1].x = 0; shape[1].y = -im; - shape[2].x = im; shape[2].y = 0; - shape[3].x = 0; shape[3].y = im; - shape[4].x =-im; shape[4].y = 0; - shape[5].x = im; shape[5].y = 0; - shape[6].x = 0; shape[6].y = im; - shape[7].x = 0; shape[7].y =-im; - SetMarkerType(2,8,shape); - } else if (markerstyle == 36) { - // square with diagonal cross - shape[0].x = -im; shape[0].y = -im; - shape[1].x = im; shape[1].y = -im; - shape[2].x = im; shape[2].y = im; - shape[3].x = -im; shape[3].y = im; - shape[4].x = -im; shape[4].y = -im; - shape[5].x = im; shape[5].y = im; - shape[6].x = -im; shape[6].y = im; - shape[7].x = im; shape[7].y = -im; - SetMarkerType(2,8,shape); - } else if (markerstyle == 37) { - // open three triangles - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = 0; - shape[1].x =-im2; shape[1].y = im; - shape[2].x = im2; shape[2].y = im; - shape[3].x = 0; shape[3].y = 0; - shape[4].x =-im2; shape[4].y = -im; - shape[5].x = -im; shape[5].y = 0; - shape[6].x = 0; shape[6].y = 0; - shape[7].x = im; shape[7].y = 0; - shape[8].x = im2; shape[8].y = -im; - shape[9].x = 0; shape[9].y = 0; - SetMarkerType(2, 10,shape); - } else if (markerstyle == 38) { - // + shaped marker with octagon - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = -im; shape[0].y = 0; - shape[1].x = -im; shape[1].y =-im2; - shape[2].x =-im2; shape[2].y = -im; - shape[3].x = im2; shape[3].y = -im; - shape[4].x = im; shape[4].y =-im2; - shape[5].x = im; shape[5].y = im2; - shape[6].x = im2; shape[6].y = im; - shape[7].x =-im2; shape[7].y = im; - shape[8].x = -im; shape[8].y = im2; - shape[9].x = -im; shape[9].y = 0; - shape[10].x = im; shape[10].y = 0; - shape[11].x = 0; shape[11].y = 0; - shape[12].x = 0; shape[12].y = -im; - shape[13].x = 0; shape[13].y = im; - shape[14].x = 0; shape[14].y = 0; - SetMarkerType(2,15,shape); - } else if (markerstyle == 39) { - // filled three triangles - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = 0; - shape[1].x =-im2; shape[1].y = im; - shape[2].x = im2; shape[2].y = im; - shape[3].x = 0; shape[3].y = 0; - shape[4].x =-im2; shape[4].y = -im; - shape[5].x = -im; shape[5].y = 0; - shape[6].x = 0; shape[6].y = 0; - shape[7].x = im; shape[7].y = 0; - shape[8].x = im2; shape[8].y = -im; - SetMarkerType(3,9,shape); - } else if (markerstyle == 40) { - // four open triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = 0; - shape[1].x = im2; shape[1].y = im; - shape[2].x = im; shape[2].y = im2; - shape[3].x = 0; shape[3].y = 0; - shape[4].x = im; shape[4].y = -im2; - shape[5].x = im2; shape[5].y = -im; - shape[6].x = 0; shape[6].y = 0; - shape[7].x = -im2; shape[7].y = -im; - shape[8].x = -im; shape[8].y = -im2; - shape[9].x = 0; shape[9].y = 0; - shape[10].x = -im; shape[10].y = im2; - shape[11].x = -im2; shape[11].y = im; - shape[12].x = 0; shape[12].y = 0; - SetMarkerType(2,13,shape); - } else if (markerstyle == 41) { - // four filled triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = 0; - shape[1].x = im2; shape[1].y = im; - shape[2].x = im; shape[2].y = im2; - shape[3].x = 0; shape[3].y = 0; - shape[4].x = im; shape[4].y = -im2; - shape[5].x = im2; shape[5].y = -im; - shape[6].x = 0; shape[6].y = 0; - shape[7].x = -im2; shape[7].y = -im; - shape[8].x = -im; shape[8].y = -im2; - shape[9].x = 0; shape[9].y = 0; - shape[10].x = -im; shape[10].y = im2; - shape[11].x = -im2; shape[11].y = im; - shape[12].x = 0; shape[12].y = 0; - SetMarkerType(3,13,shape); - } else if (markerstyle == 42) { - // open double diamonds - Int_t imx = Int_t(MarkerSizeReduced + 0.5); - shape[0].x= 0; shape[0].y= im; - shape[1].x= -imx; shape[1].y= imx; - shape[2].x = -im; shape[2].y = 0; - shape[3].x = -imx; shape[3].y = -imx; - shape[4].x = 0; shape[4].y = -im; - shape[5].x = imx; shape[5].y = -imx; - shape[6].x = im; shape[6].y = 0; - shape[7].x= imx; shape[7].y= imx; - shape[8].x= 0; shape[8].y= im; - SetMarkerType(2,9,shape); - } else if (markerstyle == 43) { - // filled double diamonds - Int_t imx = Int_t(MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = im; - shape[1].x = -imx; shape[1].y = imx; - shape[2].x = -im; shape[2].y = 0; - shape[3].x = -imx; shape[3].y = -imx; - shape[4].x = 0; shape[4].y = -im; - shape[5].x = imx; shape[5].y = -imx; - shape[6].x = im; shape[6].y = 0; - shape[7].x = imx; shape[7].y = imx; - shape[8].x = 0; shape[8].y = im; - SetMarkerType(3,9,shape); - } else if (markerstyle == 44) { - // open four triangles plus - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = 0; - shape[1].x = im2; shape[1].y = im; - shape[2].x = -im2; shape[2].y = im; - shape[3].x = im2; shape[3].y = -im; - shape[4].x = -im2; shape[4].y = -im; - shape[5].x = 0; shape[5].y = 0; - shape[6].x = im; shape[6].y = im2; - shape[7].x = im; shape[7].y = -im2; - shape[8].x = -im; shape[8].y = im2; - shape[9].x = -im; shape[9].y = -im2; - shape[10].x = 0; shape[10].y = 0; - SetMarkerType(2,11,shape); - } else if (markerstyle == 45) { - // filled four triangles plus - Int_t im0 = Int_t(0.4*MarkerSizeReduced + 0.5); - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = im0; shape[0].y = im0; - shape[1].x = im2; shape[1].y = im; - shape[2].x = -im2; shape[2].y = im; - shape[3].x = -im0; shape[3].y = im0; - shape[4].x = -im; shape[4].y = im2; - shape[5].x = -im; shape[5].y = -im2; - shape[6].x = -im0; shape[6].y = -im0; - shape[7].x = -im2; shape[7].y = -im; - shape[8].x = im2; shape[8].y = -im; - shape[9].x = im0; shape[9].y = -im0; - shape[10].x = im; shape[10].y = -im2; - shape[11].x = im; shape[11].y = im2; - shape[12].x = im0; shape[12].y = im0; - SetMarkerType(3,13,shape); - } else if (markerstyle == 46) { - // open four triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = im2; - shape[1].x = -im2; shape[1].y = im; - shape[2].x = -im; shape[2].y = im2; - shape[3].x = -im2; shape[3].y = 0; - shape[4].x = -im; shape[4].y = -im2; - shape[5].x = -im2; shape[5].y = -im; - shape[6].x = 0; shape[6].y = -im2; - shape[7].x = im2; shape[7].y = -im; - shape[8].x = im; shape[8].y = -im2; - shape[9].x = im2; shape[9].y = 0; - shape[10].x = im; shape[10].y = im2; - shape[11].x = im2; shape[11].y = im; - shape[12].x = 0; shape[12].y = im2; - SetMarkerType(2,13,shape); - } else if (markerstyle == 47) { - // filled four triangles X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = im2; - shape[1].x = -im2; shape[1].y = im; - shape[2].x = -im; shape[2].y = im2; - shape[3].x = -im2; shape[3].y = 0; - shape[4].x = -im; shape[4].y = -im2; - shape[5].x = -im2; shape[5].y = -im; - shape[6].x = 0; shape[6].y = -im2; - shape[7].x = im2; shape[7].y = -im; - shape[8].x = im; shape[8].y = -im2; - shape[9].x = im2; shape[9].y = 0; - shape[10].x = im; shape[10].y = im2; - shape[11].x = im2; shape[11].y = im; - shape[12].x = 0; shape[12].y = im2; - SetMarkerType(3,13,shape); - } else if (markerstyle == 48) { - // four filled squares X - Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); - shape[0].x = 0; shape[0].y = im2*1.005; - shape[1].x = -im2; shape[1].y = im; - shape[2].x = -im; shape[2].y = im2; - shape[3].x = -im2; shape[3].y = 0; - shape[4].x = -im; shape[4].y = -im2; - shape[5].x = -im2; shape[5].y = -im; - shape[6].x = 0; shape[6].y = -im2; - shape[7].x = im2; shape[7].y = -im; - shape[8].x = im; shape[8].y = -im2; - shape[9].x = im2; shape[9].y = 0; - shape[10].x = im; shape[10].y = im2; - shape[11].x = im2; shape[11].y = im; - shape[12].x = 0; shape[12].y = im2*0.995; - shape[13].x = im2*0.995; shape[13].y = 0; - shape[14].x = 0; shape[14].y = -im2*0.995; - shape[15].x = -im2*0.995; shape[15].y = 0; - shape[16].x = 0; shape[16].y = im2*0.995; - SetMarkerType(3,16,shape); - } else if (markerstyle == 49) { - // four filled squares plus - Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); - shape[0].x =-imx; shape[0].y =-imx*1.005; - shape[1].x =-imx; shape[1].y = -im; - shape[2].x = imx; shape[2].y = -im; - shape[3].x = imx; shape[3].y =-imx; - shape[4].x = im; shape[4].y =-imx; - shape[5].x = im; shape[5].y = imx; - shape[6].x = imx; shape[6].y = imx; - shape[7].x = imx; shape[7].y = im; - shape[8].x =-imx; shape[8].y = im; - shape[9].x =-imx; shape[9].y = imx; - shape[10].x = -im; shape[10].y = imx; - shape[11].x = -im; shape[11].y =-imx; - shape[12].x =-imx; shape[12].y =-imx*0.995; - shape[13].x =-imx; shape[13].y = imx; - shape[14].x = imx; shape[14].y = imx; - shape[15].x = imx; shape[15].y =-imx; - shape[16].x =-imx; shape[16].y =-imx*1.005; - SetMarkerType(3,17,shape); - } else { - // single dot - SetMarkerType(0,0,shape); + orgcolors[ncolors++] = pixel; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get RGB values for orgcolors, add percent neutral to the RGB and +/// allocate fNewColors. + +void TGX11::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors) +{ + if (ncolors == 0) return; + + RXColor *xcol = new RXColor[ncolors]; + + int i; + for (i = 0; i < ncolors; i++) { + xcol[i].pixel = orgcolors[i]; + xcol[i].red = xcol[i].green = xcol[i].blue = 0; + xcol[i].flags = DoRed | DoGreen | DoBlue; + } + QueryColors(fColormap, xcol, ncolors); + + UShort_t add = percent * kBIGGEST_RGB_VALUE / 100; + + Int_t val; + for (i = 0; i < ncolors; i++) { + val = xcol[i].red + add; + if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE; + xcol[i].red = (UShort_t) val; + val = xcol[i].green + add; + if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE; + xcol[i].green = (UShort_t) val; + val = xcol[i].blue + add; + if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE; + xcol[i].blue = (UShort_t) val; + if (!AllocColor(fColormap, &xcol[i])) + Warning("MakeOpaqueColors", "failed to allocate color %hd, %hd, %hd", + xcol[i].red, xcol[i].green, xcol[i].blue); + // assumes that in case of failure xcol[i].pixel is not changed + } + + gCws->fNewColors = new ULong_t[ncolors]; + gCws->fNcolors = ncolors; + + for (i = 0; i < ncolors; i++) + gCws->fNewColors[i] = xcol[i].pixel; + + delete [] xcol; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns index in orgcolors (and fNewColors) for pixel. + +Int_t TGX11::FindColor(ULong_t pixel, ULong_t *orgcolors, Int_t ncolors) +{ + for (int i = 0; i < ncolors; i++) + if (pixel == orgcolors[i]) return i; + + Error("FindColor", "did not find color, should never happen!"); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set color intensities for given color index. +/// +/// \param [in] cindex : color index +/// \param [in] r,g,b : red, green, blue intensities between 0.0 and 1.0 + +void TGX11::SetRGB(int cindex, float r, float g, float b) +{ + if (fColormap) { + RXColor xcol; + xcol.red = (UShort_t)(r * kBIGGEST_RGB_VALUE); + xcol.green = (UShort_t)(g * kBIGGEST_RGB_VALUE); + xcol.blue = (UShort_t)(b * kBIGGEST_RGB_VALUE); + xcol.flags = DoRed | DoGreen | DoBlue; + XColor_t &col = GetColor(cindex); + if (col.fDefined) { + // if color is already defined with same rgb just return + if (col.fRed == xcol.red && col.fGreen == xcol.green && + col.fBlue == xcol.blue) + return; + col.fDefined = kFALSE; + if (fRedDiv == -1) + XFreeColors((Display*)fDisplay, fColormap, &col.fPixel, 1, 0); + } + if (AllocColor(fColormap, &xcol)) { + col.fDefined = kTRUE; + col.fPixel = xcol.pixel; + col.fRed = xcol.red; + col.fGreen = xcol.green; + col.fBlue = xcol.blue; + } } } //////////////////////////////////////////////////////////////////////////////// -/// Set opacity of a window. This image manipulation routine works -/// by adding to a percent amount of neutral to each pixels RGB. -/// Since it requires quite some additional color map entries is it -/// only supported on displays with more than > 8 color planes (> 256 -/// colors). +/// Set text alignment. +/// +/// \param [in] talign text alignment -void TGX11::SetOpacity(Int_t percent) +void TGX11::SetTextAlign(Short_t talign) { - if (fDepth <= 8) return; - if (percent == 0) return; - // if 100 percent then just make white + TAttText::SetTextAlign(talign); - ULong_t *orgcolors = nullptr, *tmpc = nullptr; - Int_t maxcolors = 0, ncolors = 0, ntmpc = 0; + TAttText arg(gCws->fAttText); + arg.SetTextAlign(talign); - // save previous allocated colors, delete at end when not used anymore - if (gCws->fNewColors) { - tmpc = gCws->fNewColors; - ntmpc = gCws->fNcolors; + SetAttText((WinContext_t) gCws, arg); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set color index for text. + +void TGX11::SetTextColor(Color_t cindex) +{ + if (cindex < 0) return; + + TAttText::SetTextColor(cindex); + + TAttText arg(gCws->fAttText); + arg.SetTextColor(cindex); + + SetAttText((WinContext_t) gCws, arg); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set text font to specified name. +/// +/// \param [in] fontname font name +/// \param [in] mode loading flag +/// - mode=0 search if the font exist (kCheck) +/// - mode=1 search the font and load it if it exists (kLoad) +/// +/// Set text font to specified name. This function returns 0 if +/// the specified font is found, 1 if not. + +Int_t TGX11::SetTextFont(char *fontname, ETextSetMode mode) +{ + char **fontlist; + int fontcount; + + if (mode == kLoad) { + for (int i = 0; i < kMAXFONT; i++) { + if (strcmp(fontname, gFont[i].name) == 0) { + gTextFont = gFont[i].id; + if (gCws) { + gCws->textFont = gTextFont; + XSetFont((Display*)fDisplay, gCws->fGClist[kGCtext], gCws->textFont->fid); + XSetFont((Display*)fDisplay, gCws->fGClist[kGCinvt], gCws->textFont->fid); + } + return 0; + } + } } - // get pixmap from server as image - XImage *image = XGetImage((Display*)fDisplay, gCws->fDrawing, 0, 0, gCws->fWidth, - gCws->fHeight, AllPlanes, ZPixmap); - if (!image) return; - // collect different image colors - int x, y; - for (y = 0; y < (int) gCws->fHeight; y++) { - for (x = 0; x < (int) gCws->fWidth; x++) { - ULong_t pixel = XGetPixel(image, x, y); - CollectImageColors(pixel, orgcolors, ncolors, maxcolors); + fontlist = XListFonts((Display*)fDisplay, fontname, 1, &fontcount); + + if (fontlist && fontcount != 0) { + if (mode == kLoad) { + if (gFont[gCurrentFontNumber].id) + XFreeFont((Display*)fDisplay, gFont[gCurrentFontNumber].id); + gTextFont = XLoadQueryFont((Display*)fDisplay, fontlist[0]); + gFont[gCurrentFontNumber].id = gTextFont; + strlcpy(gFont[gCurrentFontNumber].name,fontname,80); + gCurrentFontNumber++; + if (gCurrentFontNumber == kMAXFONT) gCurrentFontNumber = 0; } + XFreeFontNames(fontlist); + return 0; + } else { + return 1; } - if (ncolors == 0) { - XDestroyImage(image); - ::operator delete(orgcolors); - return; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set current text font number. + +void TGX11::SetTextFont(Font_t fontnumber) +{ + TAttText::SetTextFont(fontnumber); + + TAttText arg(gCws->fAttText); + arg.SetTextFont(fontnumber); + + SetAttText((WinContext_t) gCws, arg); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set current text size. + +void TGX11::SetTextSize(Float_t textsize) +{ + TAttText::SetTextSize(textsize); + + TAttText arg(gCws->fAttText); + arg.SetTextSize(textsize); + + SetAttText((WinContext_t) gCws, arg); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set synchronisation on or off. +/// +/// \param [in] mode : synchronisation on/off +/// - mode=1 on +/// - mode<>0 off + +void TGX11::Sync(int mode) +{ + switch (mode) { + + case 1 : + XSynchronize((Display*)fDisplay,1); + break; + + default: + XSynchronize((Display*)fDisplay,0); + break; } +} - // create opaque counter parts - MakeOpaqueColors(percent, orgcolors, ncolors); +//////////////////////////////////////////////////////////////////////////////// +/// Update display. +/// +/// \param [in] mode : (1) update (0) sync +/// +/// Synchronise client and server once (not permanent). +/// Copy the pixmap gCws->fDrawing on the window gCws->fWindow +/// if the double buffer is on. - if (gCws->fNewColors) { - // put opaque colors in image - for (y = 0; y < (int) gCws->fHeight; y++) { - for (x = 0; x < (int) gCws->fWidth; x++) { - ULong_t pixel = XGetPixel(image, x, y); - Int_t idx = FindColor(pixel, orgcolors, ncolors); - XPutPixel(image, x, y, gCws->fNewColors[idx]); - } - } +void TGX11::UpdateWindow(int mode) +{ + UpdateWindowW((WinContext_t) gCws, mode); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Update display for specified window. +/// +/// \param [in] mode : (1) update (0) sync +/// +/// Synchronise client and server once (not permanent). +/// Copy the pixmap gCws->fDrawing on the window gCws->fWindow +/// if the double buffer is on. + +void TGX11::UpdateWindowW(WinContext_t wctxt, Int_t mode) +{ + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; + + if (ctxt->fDoubleBuffer) { + XCopyArea((Display*)fDisplay, ctxt->fDrawing, ctxt->fWindow, + ctxt->fGClist[kGCpxmp], 0, 0, ctxt->fWidth, ctxt->fHeight, 0, 0); + } + if (mode == 1) { + XFlush((Display*)fDisplay); + } else { + XSync((Display*)fDisplay, False); } +} - // put image back in pixmap on server - XPutImage((Display*)fDisplay, gCws->fDrawing, *gGCpxmp, image, 0, 0, 0, 0, - gCws->fWidth, gCws->fHeight); - XFlush((Display*)fDisplay); +//////////////////////////////////////////////////////////////////////////////// +/// Set pointer position. +/// +/// \param [in] ix New X coordinate of pointer +/// \param [in] iy New Y coordinate of pointer +/// \param [in] id Window identifier +/// +/// Coordinates are relative to the origin of the window id +/// or to the origin of the current window if id == 0. - // clean up - if (tmpc) { - if (fRedDiv == -1) - XFreeColors((Display*)fDisplay, fColormap, tmpc, ntmpc, 0); - delete [] tmpc; +void TGX11::Warp(Int_t ix, Int_t iy, Window_t id) +{ + if (!id) { + // Causes problems when calling ProcessEvents()... BadWindow + //XWarpPointer((Display*)fDisplay, None, gCws->fWindow, 0, 0, 0, 0, ix, iy); + } else { + XWarpPointer((Display*)fDisplay, None, (Window) id, 0, 0, 0, 0, ix, iy); } - XDestroyImage(image); - ::operator delete(orgcolors); } //////////////////////////////////////////////////////////////////////////////// -/// Collect in orgcolors all different original image colors. +/// Write the pixmap wid in the bitmap file pxname. +/// +/// \param [in] wid : Pixmap address +/// \param [in] w,h : Width and height of the pixmap. +/// \param [in] pxname : pixmap name + +void TGX11::WritePixmap(int wid, unsigned int w, unsigned int h, char *pxname) +{ + unsigned int wval, hval; + wval = w; + hval = h; + + gTws = fWindows[wid].get(); + XWriteBitmapFile((Display*)fDisplay, pxname, gTws->fDrawing, wval, hval, -1, -1); +} + + +// +// Functions for GIFencode() +// + +static FILE *gOut; // output unit used WriteGIF and PutByte +static XImage *gXimage = nullptr; // image used in WriteGIF and GetPixel + +extern "C" { + int GIFquantize(UInt_t width, UInt_t height, Int_t *ncol, Byte_t *red, Byte_t *green, + Byte_t *blue, Byte_t *outputBuf, Byte_t *outputCmap); + long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[], Byte_t G[], Byte_t B[], Byte_t ScLine[], + void (*get_scline) (int, int, Byte_t *), void (*pb)(Byte_t)); + int GIFdecode(Byte_t *gifArr, Byte_t *pixArr, int *Width, int *Height, int *Ncols, Byte_t *R, Byte_t *G, Byte_t *B); + int GIFinfo(Byte_t *gifArr, int *Width, int *Height, int *Ncols); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get pixels in line y and put in array scline. -void TGX11::CollectImageColors(ULong_t pixel, ULong_t *&orgcolors, Int_t &ncolors, - Int_t &maxcolors) +static void GetPixel(int y, int width, Byte_t *scline) { - if (maxcolors == 0) { - ncolors = 0; - maxcolors = 100; - orgcolors = (ULong_t*) ::operator new(maxcolors*sizeof(ULong_t)); - } - - for (int i = 0; i < ncolors; i++) - if (pixel == orgcolors[i]) return; + for (int i = 0; i < width; i++) + scline[i] = Byte_t(XGetPixel(gXimage, i, y)); +} - if (ncolors >= maxcolors) { - orgcolors = (ULong_t*) TStorage::ReAlloc(orgcolors, - maxcolors*2*sizeof(ULong_t), maxcolors*sizeof(ULong_t)); - maxcolors *= 2; - } +//////////////////////////////////////////////////////////////////////////////// +/// Put byte b in output stream. - orgcolors[ncolors++] = pixel; +static void PutByte(Byte_t b) +{ + if (ferror(gOut) == 0) fputc(b, gOut); } //////////////////////////////////////////////////////////////////////////////// -/// Get RGB values for orgcolors, add percent neutral to the RGB and -/// allocate fNewColors. +/// Returns in R G B the ncol colors of the palette used by the image. +/// The image pixels are changed to index values in these R G B arrays. +/// This produces a colormap with only the used colors (so even on displays +/// with more than 8 planes we will be able to create GIF's when the image +/// contains no more than 256 different colors). If it does contain more +/// colors we will have to use GIFquantize to reduce the number of colors. +/// The R G B arrays must be deleted by the caller. -void TGX11::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors) +void TGX11::ImgPickPalette(RXImage *image, Int_t &ncol, Int_t *&R, Int_t *&G, Int_t *&B) { - if (ncolors == 0) return; + ULong_t *orgcolors = nullptr; + Int_t maxcolors = 0, ncolors = 0; + + // collect different image colors + int x, y; + for (x = 0; x < (int) gCws->fWidth; x++) { + for (y = 0; y < (int) gCws->fHeight; y++) { + ULong_t pixel = XGetPixel(image, x, y); + CollectImageColors(pixel, orgcolors, ncolors, maxcolors); + } + } + // get RGB values belonging to pixels RXColor *xcol = new RXColor[ncolors]; int i; @@ -3014,714 +2902,1050 @@ void TGX11::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors) } QueryColors(fColormap, xcol, ncolors); - UShort_t add = percent * kBIGGEST_RGB_VALUE / 100; + // create RGB arrays and store RGB's for each color and set number of colors + // (space must be delete by caller) + R = new Int_t[ncolors]; + G = new Int_t[ncolors]; + B = new Int_t[ncolors]; - Int_t val; for (i = 0; i < ncolors; i++) { - val = xcol[i].red + add; - if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE; - xcol[i].red = (UShort_t) val; - val = xcol[i].green + add; - if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE; - xcol[i].green = (UShort_t) val; - val = xcol[i].blue + add; - if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE; - xcol[i].blue = (UShort_t) val; - if (!AllocColor(fColormap, &xcol[i])) - Warning("MakeOpaqueColors", "failed to allocate color %hd, %hd, %hd", - xcol[i].red, xcol[i].green, xcol[i].blue); - // assumes that in case of failure xcol[i].pixel is not changed + R[i] = xcol[i].red; + G[i] = xcol[i].green; + B[i] = xcol[i].blue; } + ncol = ncolors; - gCws->fNewColors = new ULong_t[ncolors]; - gCws->fNcolors = ncolors; - - for (i = 0; i < ncolors; i++) - gCws->fNewColors[i] = xcol[i].pixel; + // update image with indices (pixels) into the new RGB colormap + for (x = 0; x < (int) gCws->fWidth; x++) { + for (y = 0; y < (int) gCws->fHeight; y++) { + ULong_t pixel = XGetPixel(image, x, y); + Int_t idx = FindColor(pixel, orgcolors, ncolors); + XPutPixel(image, x, y, idx); + } + } + // cleanup delete [] xcol; + ::operator delete(orgcolors); } //////////////////////////////////////////////////////////////////////////////// -/// Returns index in orgcolors (and fNewColors) for pixel. +/// Writes the current window into GIF file. Returns 1 in case of success, +/// 0 otherwise. -Int_t TGX11::FindColor(ULong_t pixel, ULong_t *orgcolors, Int_t ncolors) +Int_t TGX11::WriteGIF(char *name) { - for (int i = 0; i < ncolors; i++) - if (pixel == orgcolors[i]) return i; + Byte_t scline[2000], r[256], b[256], g[256]; + Int_t *red, *green, *blue; + Int_t ncol, maxcol, i; - Error("FindColor", "did not find color, should never happen!"); + if (gXimage) { + XDestroyImage(gXimage); + gXimage = nullptr; + } - return 0; -} + gXimage = XGetImage((Display*)fDisplay, gCws->fDrawing, 0, 0, + gCws->fWidth, gCws->fHeight, + AllPlanes, ZPixmap); -//////////////////////////////////////////////////////////////////////////////// -/// Set color intensities for given color index. -/// -/// \param [in] cindex : color index -/// \param [in] r,g,b : red, green, blue intensities between 0.0 and 1.0 + ImgPickPalette((RXImage*)gXimage, ncol, red, green, blue); -void TGX11::SetRGB(int cindex, float r, float g, float b) -{ - if (fColormap) { - RXColor xcol; - xcol.red = (UShort_t)(r * kBIGGEST_RGB_VALUE); - xcol.green = (UShort_t)(g * kBIGGEST_RGB_VALUE); - xcol.blue = (UShort_t)(b * kBIGGEST_RGB_VALUE); - xcol.flags = DoRed | DoGreen | DoBlue; - XColor_t &col = GetColor(cindex); - if (col.fDefined) { - // if color is already defined with same rgb just return - if (col.fRed == xcol.red && col.fGreen == xcol.green && - col.fBlue == xcol.blue) - return; - col.fDefined = kFALSE; - if (fRedDiv == -1) - XFreeColors((Display*)fDisplay, fColormap, &col.fPixel, 1, 0); - } - if (AllocColor(fColormap, &xcol)) { - col.fDefined = kTRUE; - col.fPixel = xcol.pixel; - col.fRed = xcol.red; - col.fGreen = xcol.green; - col.fBlue = xcol.blue; + if (ncol > 256) { + //GIFquantize(...); + Error("WriteGIF", "Cannot create GIF of image containing more than 256 colors. Try in batch mode."); + delete [] red; + delete [] green; + delete [] blue; + return 0; + } + + maxcol = 0; + for (i = 0; i < ncol; i++) { + if (maxcol < red[i] ) maxcol = red[i]; + if (maxcol < green[i] ) maxcol = green[i]; + if (maxcol < blue[i] ) maxcol = blue[i]; + r[i] = 0; + g[i] = 0; + b[i] = 0; + } + if (maxcol != 0) { + for (i = 0; i < ncol; i++) { + r[i] = red[i] * 255/maxcol; + g[i] = green[i] * 255/maxcol; + b[i] = blue[i] * 255/maxcol; } } + + gOut = fopen(name, "w+"); + + if (gOut) { + GIFencode(gCws->fWidth, gCws->fHeight, + ncol, r, g, b, scline, ::GetPixel, PutByte); + fclose(gOut); + i = 1; + } else { + Error("WriteGIF","cannot write file: %s",name); + i = 0; + } + delete [] red; + delete [] green; + delete [] blue; + return i; } //////////////////////////////////////////////////////////////////////////////// -/// Set text alignment. -/// -/// \param [in] talign text alignment +/// Draw image. +/// Not used, keep for backward compatibility -void TGX11::SetTextAlign(Short_t talign) +void TGX11::PutImage(Int_t offset,Int_t itran,Int_t x0,Int_t y0,Int_t nx,Int_t ny,Int_t xmin, + Int_t ymin,Int_t xmax,Int_t ymax, UChar_t *image,Drawable_t wid) { - Int_t txalh = talign/10; - Int_t txalv = talign%10; - fTextAlignH = txalh; - fTextAlignV = txalv; + const int maxSegment = 20; + int i, n, x, y, xcur, x1, x2, y1, y2; + unsigned char *jimg, *jbase, icol; + int nlines[256]; + XSegment lines[256][maxSegment]; + Drawable_t id; + GC lineGC; - switch (txalh) { + if (wid) { + id = wid; + lineGC = XCreateGC((Display*)fDisplay, fVisRootWin, 0, nullptr); + } else { + id = gCws->fDrawing; + lineGC = gCws->fGClist[kGCline]; + } - case 0 : - case 1 : - switch (txalv) { //left - case 1 : - fTextAlign = 7; //bottom - break; - case 2 : - fTextAlign = 4; //center - break; - case 3 : - fTextAlign = 1; //top - break; - } - break; - case 2 : - switch (txalv) { //center - case 1 : - fTextAlign = 8; //bottom - break; - case 2 : - fTextAlign = 5; //center - break; - case 3 : - fTextAlign = 2; //top - break; - } - break; - case 3 : - switch (txalv) { //right - case 1 : - fTextAlign = 9; //bottom - break; - case 2 : - fTextAlign = 6; //center - break; - case 3 : - fTextAlign = 3; //top - break; + for (i = 0; i < 256; i++) nlines[i] = 0; + + x1 = x0 + xmin; y1 = y0 + ny - ymax - 1; + x2 = x0 + xmax; y2 = y0 + ny - ymin - 1; + jbase = image + (ymin-1)*nx + xmin; + + for (y = y2; y >= y1; y--) { + xcur = x1; jbase += nx; + for (jimg = jbase, icol = *jimg++, x = x1+1; x <= x2; jimg++, x++) { + if (icol != *jimg) { + if (icol != itran) { + n = nlines[icol]++; + lines[icol][n].x1 = xcur; lines[icol][n].y1 = y; + lines[icol][n].x2 = x-1; lines[icol][n].y2 = y; + if (nlines[icol] == maxSegment) { + SetColor(wid ? nullptr : gCws, &lineGC, (int)icol+offset); + XDrawSegments((Display*)fDisplay,id,lineGC,&lines[icol][0], + maxSegment); + nlines[icol] = 0; + } + } + icol = *jimg; xcur = x; } - break; + } + if (icol != itran) { + n = nlines[icol]++; + lines[icol][n].x1 = xcur; lines[icol][n].y1 = y; + lines[icol][n].x2 = x-1; lines[icol][n].y2 = y; + if (nlines[icol] == maxSegment) { + SetColor(wid ? nullptr : gCws, &lineGC, (int)icol+offset); + XDrawSegments((Display*)fDisplay,id,lineGC,&lines[icol][0], + maxSegment); + nlines[icol] = 0; + } + } + } + + for (i = 0; i < 256; i++) { + if (nlines[i] != 0) { + SetColor(wid ? nullptr : gCws, &lineGC,i+offset); + XDrawSegments((Display*)fDisplay,id,lineGC,&lines[i][0],nlines[i]); + } } - TAttText::SetTextAlign(fTextAlign); + if (wid) + XFreeGC((Display*)fDisplay, lineGC); } //////////////////////////////////////////////////////////////////////////////// -/// Set color index for text. +/// If id is NULL - loads the specified gif file at position [x0,y0] in the +/// current window. Otherwise creates pixmap from gif file -void TGX11::SetTextColor(Color_t cindex) +Pixmap_t TGX11::ReadGIF(int x0, int y0, const char *file, Window_t id) { - if (cindex < 0) return; - - TAttText::SetTextColor(cindex); + FILE *fd; + Seek_t filesize = 0; + unsigned char *gifArr, *pixArr, red[256], green[256], blue[256], *j1, *j2, icol; + int i, j, k, width, height, ncolor, irep, offset; + float rr, gg, bb; + Pixmap_t pic = 0; - SetColor(gGCtext, Int_t(cindex)); + fd = fopen(file, "r"); + if (!fd) { + Error("ReadGIF", "unable to open GIF file"); + return pic; + } - XGCValues values; - if (XGetGCValues((Display*)fDisplay, *gGCtext, GCForeground | GCBackground, &values)) { - XSetForeground( (Display*)fDisplay, *gGCinvt, values.background ); - XSetBackground( (Display*)fDisplay, *gGCinvt, values.foreground ); + fseek(fd, 0L, 2); + long ft = ftell(fd); + if (ft <=0) { + Error("ReadGIF", "unable to open GIF file"); + fclose(fd); + return pic; } else { - Error("SetTextColor", "cannot get GC values"); + filesize = Seek_t(ft); } - XSetBackground((Display*)fDisplay, *gGCtext, GetColor(0).fPixel); -} + fseek(fd, 0L, 0); -//////////////////////////////////////////////////////////////////////////////// -/// Set text font to specified name. -/// -/// \param [in] fontname font name -/// \param [in] mode loading flag -/// - mode=0 search if the font exist (kCheck) -/// - mode=1 search the font and load it if it exists (kLoad) -/// -/// Set text font to specified name. This function returns 0 if -/// the specified font is found, 1 if not. + if (!(gifArr = (unsigned char *) calloc(filesize+256,1))) { + Error("ReadGIF", "unable to allocate array for gif"); + fclose(fd); + return pic; + } -Int_t TGX11::SetTextFont(char *fontname, ETextSetMode mode) -{ - char **fontlist; - int fontcount; - int i; + if (fread(gifArr, filesize, 1, fd) != 1) { + Error("ReadGIF", "GIF file read failed"); + free(gifArr); + fclose(fd); + return pic; + } + fclose(fd); - if (mode == kLoad) { - for (i = 0; i < kMAXFONT; i++) { - if (strcmp(fontname, gFont[i].name) == 0) { - gTextFont = gFont[i].id; - XSetFont((Display*)fDisplay, *gGCtext, gTextFont->fid); - XSetFont((Display*)fDisplay, *gGCinvt, gTextFont->fid); - return 0; - } - } + irep = GIFinfo(gifArr, &width, &height, &ncolor); + if (irep != 0) { + free(gifArr); + return pic; } - fontlist = XListFonts((Display*)fDisplay, fontname, 1, &fontcount); + if (!(pixArr = (unsigned char *) calloc((width*height),1))) { + Error("ReadGIF", "unable to allocate array for image"); + free(gifArr); + return pic; + } - if (fontlist && fontcount != 0) { - if (mode == kLoad) { - if (gFont[gCurrentFontNumber].id) - XFreeFont((Display*)fDisplay, gFont[gCurrentFontNumber].id); - gTextFont = XLoadQueryFont((Display*)fDisplay, fontlist[0]); - XSetFont((Display*)fDisplay, *gGCtext, gTextFont->fid); - XSetFont((Display*)fDisplay, *gGCinvt, gTextFont->fid); - gFont[gCurrentFontNumber].id = gTextFont; - strlcpy(gFont[gCurrentFontNumber].name,fontname,80); - gCurrentFontNumber++; - if (gCurrentFontNumber == kMAXFONT) gCurrentFontNumber = 0; + irep = GIFdecode(gifArr, pixArr, &width, &height, &ncolor, red, green, blue); + if (irep != 0) { + free(gifArr); + free(pixArr); + return pic; + } + + // S E T P A L E T T E + + offset = 8; + + for (i = 0; i < ncolor; i++) { + rr = red[i]/255.; + gg = green[i]/255.; + bb = blue[i]/255.; + j = i+offset; + SetRGB(j,rr,gg,bb); + } + + // O U T P U T I M A G E + + for (i = 1; i <= height/2; i++) { + j1 = pixArr + (i-1)*width; + j2 = pixArr + (height-i)*width; + for (k = 0; k < width; k++) { + icol = *j1; *j1++ = *j2; *j2++ = icol; } - XFreeFontNames(fontlist); - return 0; - } else { - return 1; } + if (id) pic = CreatePixmap(id, width, height); + PutImage(offset,-1,x0,y0,width,height,0,0,width-1,height-1,pixArr,pic); + + free(gifArr); + free(pixArr); + + if (pic) + return pic; + else if (gCws->fDrawing) + return (Pixmap_t)gCws->fDrawing; + return 0; } //////////////////////////////////////////////////////////////////////////////// -/// Set current text font number. +/// Returns an array of pixels created from a part of drawable +/// (defined by x, y, w, h) in format: +/// `b1, g1, r1, 0, b2, g2, r2, 0, ..., bn, gn, rn, 0`. +/// +/// Pixels are numbered from left to right and from top to bottom. +/// By default all pixels from the whole drawable are returned. +/// +/// Note that return array is 32-bit aligned -void TGX11::SetTextFont(Font_t fontnumber) +unsigned char *TGX11::GetColorBits(Drawable_t /*wid*/, Int_t /*x*/, Int_t /*y*/, + UInt_t /*w*/, UInt_t /*h*/) { - fTextFont = fontnumber; + return nullptr; } //////////////////////////////////////////////////////////////////////////////// -/// Set current text size. +/// create pixmap from RGB data. RGB data is in format : +/// b1, g1, r1, 0, b2, g2, r2, 0 ... bn, gn, rn, 0 .. +/// +/// Pixels are numbered from left to right and from top to bottom. +/// Note that data must be 32-bit aligned -void TGX11::SetTextSize(Float_t textsize) +Pixmap_t TGX11::CreatePixmapFromData(unsigned char * /*bits*/, UInt_t /*width*/, + UInt_t /*height*/) { - fTextSize = textsize; + return (Pixmap_t)0; } //////////////////////////////////////////////////////////////////////////////// -/// Set synchronisation on or off. +/// Register pixmap created by gVirtualGL /// -/// \param [in] mode : synchronisation on/off -/// - mode=1 on -/// - mode<>0 off +/// \param [in] pixid Pixmap identifier +/// \param [in] w,h Width and height of the pixmap +/// +/// register new pixmap -void TGX11::Sync(int mode) +Int_t TGX11::AddPixmap(ULong_t pixid, UInt_t w, UInt_t h) { - switch (mode) { + Int_t wid = AddWindowHandle(); - case 1 : - XSynchronize((Display*)fDisplay,1); - break; + gCws = fWindows[wid].get(); + gCws->fWindow = pixid; + gCws->fDrawing = gCws->fWindow; + gCws->fBuffer = 0; + gCws->fDoubleBuffer = 0; + gCws->fIsPixmap = 1; + gCws->fClip = 0; + gCws->fWidth = w; + gCws->fHeight = h; + gCws->fNewColors = nullptr; + gCws->fShared = kFALSE; - default: - XSynchronize((Display*)fDisplay,0); - break; - } + return wid; } //////////////////////////////////////////////////////////////////////////////// -/// Update display. -/// -/// \param [in] mode : (1) update (0) sync -/// -/// Synchronise client and server once (not permanent). -/// Copy the pixmap gCws->fDrawing on the window gCws->fWindow -/// if the double buffer is on. +/// Returns 1 if window system server supports extension given by the +/// argument, returns 0 in case extension is not supported and returns -1 +/// in case of error (like server not initialized). +/// Examples: +/// - "Apple-WM" - does server run on MacOS X; +/// - "XINERAMA" - does server support Xinerama. +/// See also the output of xdpyinfo. -void TGX11::UpdateWindow(int mode) +Int_t TGX11::SupportsExtension(const char *ext) const { - if (gCws->fDoubleBuffer) { - XCopyArea((Display*)fDisplay, gCws->fDrawing, gCws->fWindow, - *gGCpxmp, 0, 0, gCws->fWidth, gCws->fHeight, 0, 0); - } - if (mode == 1) { - XFlush((Display*)fDisplay); - } else { - XSync((Display*)fDisplay, False); - } + Int_t major_opcode, first_event, first_error; + if (!(Display*)fDisplay) + return -1; + return XQueryExtension((Display*)fDisplay, ext, &major_opcode, &first_event, &first_error); } -//////////////////////////////////////////////////////////////////////////////// -/// Set pointer position. -/// -/// \param [in] ix New X coordinate of pointer -/// \param [in] iy New Y coordinate of pointer -/// \param [in] id Window identifier -/// -/// Coordinates are relative to the origin of the window id -/// or to the origin of the current window if id == 0. -void TGX11::Warp(Int_t ix, Int_t iy, Window_t id) +WinContext_t TGX11::GetWindowContext(Int_t wid) { - if (!id) { - // Causes problems when calling ProcessEvents()... BadWindow - //XWarpPointer((Display*)fDisplay, None, gCws->fWindow, 0, 0, 0, 0, ix, iy); - } else { - XWarpPointer((Display*)fDisplay, None, (Window) id, 0, 0, 0, 0, ix, iy); - } + return (WinContext_t) fWindows[wid].get(); } -//////////////////////////////////////////////////////////////////////////////// -/// Write the pixmap wid in the bitmap file pxname. -/// -/// \param [in] wid : Pixmap address -/// \param [in] w,h : Width and height of the pixmap. -/// \param [in] pxname : pixmap name - -void TGX11::WritePixmap(int wid, unsigned int w, unsigned int h, char *pxname) +void TGX11::SetAttFill(WinContext_t wctxt, const TAttFill &att) { - unsigned int wval, hval; - wval = w; - hval = h; + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - gTws = &fWindows[wid]; - XWriteBitmapFile((Display*)fDisplay, pxname, gTws->fDrawing, wval, hval, -1, -1); -} + Int_t cindex = att.GetFillColor(); + if (!gStyle->GetFillColor() && cindex > 1) + cindex = 0; + if (cindex >= 0) + SetColor(ctxt, &ctxt->fGClist[kGCfill], Int_t(cindex)); + ctxt->fAttFill.SetFillColor(cindex); + Int_t style = att.GetFillStyle() / 1000; + Int_t fasi = att.GetFillStyle() % 1000; + Int_t stn = (fasi >= 1 && fasi <=25) ? fasi : 2; + ctxt->fAttFill.SetFillStyle(style * 1000 + fasi); -// -// Functions for GIFencode() -// + switch (style) { + case 1: // solid + ctxt->fillHollow = 0; + XSetFillStyle((Display*)fDisplay, ctxt->fGClist[kGCfill], FillSolid); + break; -static FILE *gOut; // output unit used WriteGIF and PutByte -static XImage *gXimage = nullptr; // image used in WriteGIF and GetPixel + case 2: // pattern + ctxt->fillHollow = 1; + break; -extern "C" { - int GIFquantize(UInt_t width, UInt_t height, Int_t *ncol, Byte_t *red, Byte_t *green, - Byte_t *blue, Byte_t *outputBuf, Byte_t *outputCmap); - long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[], Byte_t G[], Byte_t B[], Byte_t ScLine[], - void (*get_scline) (int, int, Byte_t *), void (*pb)(Byte_t)); - int GIFdecode(Byte_t *gifArr, Byte_t *pixArr, int *Width, int *Height, int *Ncols, Byte_t *R, Byte_t *G, Byte_t *B); - int GIFinfo(Byte_t *gifArr, int *Width, int *Height, int *Ncols); -} + case 3: // hatch + ctxt->fillHollow = 0; + XSetFillStyle((Display*)fDisplay, ctxt->fGClist[kGCfill], FillStippled); -//////////////////////////////////////////////////////////////////////////////// -/// Get pixels in line y and put in array scline. + if (stn != ctxt->fillFasi) { + if (ctxt->fillPattern != 0) + XFreePixmap((Display*)fDisplay, ctxt->fillPattern); -static void GetPixel(int y, int width, Byte_t *scline) -{ - for (int i = 0; i < width; i++) - scline[i] = Byte_t(XGetPixel(gXimage, i, y)); -} + ctxt->fillPattern = XCreateBitmapFromData((Display*)fDisplay, fRootWin, + (const char*)gStipples[stn], 16, 16); -//////////////////////////////////////////////////////////////////////////////// -/// Put byte b in output stream. + XSetStipple((Display*)fDisplay, ctxt->fGClist[kGCfill], ctxt->fillPattern); + ctxt->fillFasi = stn; + } + break; -static void PutByte(Byte_t b) -{ - if (ferror(gOut) == 0) fputc(b, gOut); + default: + ctxt->fillHollow = 1; + } } -//////////////////////////////////////////////////////////////////////////////// -/// Returns in R G B the ncol colors of the palette used by the image. -/// The image pixels are changed to index values in these R G B arrays. -/// This produces a colormap with only the used colors (so even on displays -/// with more than 8 planes we will be able to create GIF's when the image -/// contains no more than 256 different colors). If it does contain more -/// colors we will have to use GIFquantize to reduce the number of colors. -/// The R G B arrays must be deleted by the caller. - -void TGX11::ImgPickPalette(RXImage *image, Int_t &ncol, Int_t *&R, Int_t *&G, Int_t *&B) +void TGX11::SetAttLine(WinContext_t wctxt, const TAttLine &att) { - ULong_t *orgcolors = nullptr; - Int_t maxcolors = 0, ncolors = 0; + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - // collect different image colors - int x, y; - for (x = 0; x < (int) gCws->fWidth; x++) { - for (y = 0; y < (int) gCws->fHeight; y++) { - ULong_t pixel = XGetPixel(image, x, y); - CollectImageColors(pixel, orgcolors, ncolors, maxcolors); + if (ctxt->fAttLine.GetLineStyle() != att.GetLineStyle()) { //set style index only if different + if (att.GetLineStyle() <= 1) + ctxt->dashList.clear(); + else if (att.GetLineStyle() == 2) + ctxt->dashList = { 3, 3 }; + else if (att.GetLineStyle() == 3) + ctxt->dashList = { 1, 2 }; + else if (att.GetLineStyle() == 4) { + ctxt->dashList = { 3, 4, 1, 4} ; + } else { + TString st = (TString)gStyle->GetLineStyleString(att.GetLineStyle()); + auto tokens = st.Tokenize(" "); + Int_t nt = tokens->GetEntries(); + ctxt->dashList.resize(nt); + for (Int_t j = 0; j < nt; ++j) { + Int_t it; + sscanf(tokens->At(j)->GetName(), "%d", &it); + ctxt->dashList[j] = (Int_t) (it/4); + } + delete tokens; } + ctxt->dashLength = 0; + for (auto elem : ctxt->dashList) + ctxt->dashLength += elem; + ctxt->dashOffset = 0; + ctxt->lineStyle = ctxt->dashList.size() == 0 ? LineSolid : LineOnOffDash; } - // get RGB values belonging to pixels - RXColor *xcol = new RXColor[ncolors]; - - int i; - for (i = 0; i < ncolors; i++) { - xcol[i].pixel = orgcolors[i]; - xcol[i].red = xcol[i].green = xcol[i].blue = 0; - xcol[i].flags = DoRed | DoGreen | DoBlue; + ctxt->lineWidth = att.GetLineWidth(); + if (ctxt->lineStyle == LineSolid) { + if (ctxt->lineWidth == 1) + ctxt->lineWidth = 0; + } else { + if (ctxt->lineWidth == 0) + ctxt->lineWidth = 1; } - QueryColors(fColormap, xcol, ncolors); - - // create RGB arrays and store RGB's for each color and set number of colors - // (space must be delete by caller) - R = new Int_t[ncolors]; - G = new Int_t[ncolors]; - B = new Int_t[ncolors]; - for (i = 0; i < ncolors; i++) { - R[i] = xcol[i].red; - G[i] = xcol[i].green; - B[i] = xcol[i].blue; + if (ctxt->lineWidth >= 0) { + XSetLineAttributes((Display*)fDisplay, ctxt->fGClist[kGCline], ctxt->lineWidth, + ctxt->lineStyle, gCapStyle, gJoinStyle); + if (ctxt->lineStyle == LineOnOffDash) + XSetLineAttributes((Display*)fDisplay, ctxt->fGClist[kGCdash], ctxt->lineWidth, + ctxt->lineStyle, gCapStyle, gJoinStyle); } - ncol = ncolors; - // update image with indices (pixels) into the new RGB colormap - for (x = 0; x < (int) gCws->fWidth; x++) { - for (y = 0; y < (int) gCws->fHeight; y++) { - ULong_t pixel = XGetPixel(image, x, y); - Int_t idx = FindColor(pixel, orgcolors, ncolors); - XPutPixel(image, x, y, idx); - } + if (att.GetLineColor() >= 0) { + SetColor(ctxt, &ctxt->fGClist[kGCline], (Int_t) att.GetLineColor()); + SetColor(ctxt, &ctxt->fGClist[kGCdash], (Int_t) att.GetLineColor()); } - // cleanup - delete [] xcol; - ::operator delete(orgcolors); + ctxt->fAttLine = att; } -//////////////////////////////////////////////////////////////////////////////// -/// Writes the current window into GIF file. Returns 1 in case of success, -/// 0 otherwise. - -Int_t TGX11::WriteGIF(char *name) +void TGX11::SetAttMarker(WinContext_t wctxt, const TAttMarker &att) { - Byte_t scline[2000], r[256], b[256], g[256]; - Int_t *red, *green, *blue; - Int_t ncol, maxcol, i; + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - if (gXimage) { - XDestroyImage(gXimage); - gXimage = nullptr; - } + SetColor(ctxt, &ctxt->fGClist[kGCmark], att.GetMarkerColor()); - gXimage = XGetImage((Display*)fDisplay, gCws->fDrawing, 0, 0, - gCws->fWidth, gCws->fHeight, - AllPlanes, ZPixmap); + Bool_t changed = (att.GetMarkerSize() != ctxt->fAttMarker.GetMarkerSize()) || + (att.GetMarkerStyle() != ctxt->fAttMarker.GetMarkerStyle()); - ImgPickPalette((RXImage*)gXimage, ncol, red, green, blue); + ctxt->fAttMarker = att; - if (ncol > 256) { - //GIFquantize(...); - Error("WriteGIF", "Cannot create GIF of image containing more than 256 colors. Try in batch mode."); - delete [] red; - delete [] green; - delete [] blue; - return 0; - } + if (!changed) + return; - maxcol = 0; - for (i = 0; i < ncol; i++) { - if (maxcol < red[i] ) maxcol = red[i]; - if (maxcol < green[i] ) maxcol = green[i]; - if (maxcol < blue[i] ) maxcol = blue[i]; - r[i] = 0; - g[i] = 0; - b[i] = 0; - } - if (maxcol != 0) { - for (i = 0; i < ncol; i++) { - r[i] = red[i] * 255/maxcol; - g[i] = green[i] * 255/maxcol; - b[i] = blue[i] * 255/maxcol; - } - } + Int_t markerstyle = TAttMarker::GetMarkerStyleBase(att.GetMarkerStyle()); + ctxt->markerLineWidth = TAttMarker::GetMarkerLineWidth(att.GetMarkerStyle()); - gOut = fopen(name, "w+"); + // The fast pixel markers need to be treated separately + if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) { + XSetLineAttributes((Display*)fDisplay, ctxt->fGClist[kGCmark], 0, LineSolid, CapButt, JoinMiter); + } else { + XSetLineAttributes((Display*)fDisplay, ctxt->fGClist[kGCmark], ctxt->markerLineWidth, + gMarkerLineStyle, gMarkerCapStyle, gMarkerJoinStyle); + } - if (gOut) { - GIFencode(gCws->fWidth, gCws->fHeight, - ncol, r, g, b, scline, ::GetPixel, PutByte); - fclose(gOut); - i = 1; + Float_t MarkerSizeReduced = att.GetMarkerSize() - TMath::Floor(ctxt->markerLineWidth/2.)/4.; + Int_t im = Int_t(4*MarkerSizeReduced + 0.5); + auto &shape = ctxt->markerShape; + ctxt->markerSize = 0; + ctxt->markerType = 0; + if (markerstyle == 2) { + // + shaped marker + shape.resize(4); + shape[0].x = -im; shape[0].y = 0; + shape[1].x = im; shape[1].y = 0; + shape[2].x = 0 ; shape[2].y = -im; + shape[3].x = 0 ; shape[3].y = im; + ctxt->markerType = 4; + } else if (markerstyle == 3 || markerstyle == 31) { + // * shaped marker + shape.resize(8); + shape[0].x = -im; shape[0].y = 0; + shape[1].x = im; shape[1].y = 0; + shape[2].x = 0 ; shape[2].y = -im; + shape[3].x = 0 ; shape[3].y = im; + im = Int_t(0.707*Float_t(im) + 0.5); + shape[4].x = -im; shape[4].y = -im; + shape[5].x = im; shape[5].y = im; + shape[6].x = -im; shape[6].y = im; + shape[7].x = im; shape[7].y = -im; + ctxt->markerType = 4; + } else if (markerstyle == 4 || markerstyle == 24) { + // O shaped marker + shape.resize(0); + ctxt->markerType = 0; + ctxt->markerSize = im*2; + } else if (markerstyle == 5) { + // X shaped marker + shape.resize(4); + im = Int_t(0.707*Float_t(im) + 0.5); + shape[0].x = -im; shape[0].y = -im; + shape[1].x = im; shape[1].y = im; + shape[2].x = -im; shape[2].y = im; + shape[3].x = im; shape[3].y = -im; + ctxt->markerType = 4; + } else if (markerstyle == 6) { + // + shaped marker (with 1 pixel) + shape.resize(4); + shape[0].x = -1 ; shape[0].y = 0; + shape[1].x = 1 ; shape[1].y = 0; + shape[2].x = 0 ; shape[2].y = -1; + shape[3].x = 0 ; shape[3].y = 1; + ctxt->markerType = 4; + } else if (markerstyle == 7) { + // . shaped marker (with 9 pixel) + shape.resize(6); + shape[0].x = -1 ; shape[0].y = 1; + shape[1].x = 1 ; shape[1].y = 1; + shape[2].x = -1 ; shape[2].y = 0; + shape[3].x = 1 ; shape[3].y = 0; + shape[4].x = -1 ; shape[4].y = -1; + shape[5].x = 1 ; shape[5].y = -1; + ctxt->markerType = 4; + } else if (markerstyle == 8 || markerstyle == 20) { + // O shaped marker (filled) + shape.resize(0); + ctxt->markerType = 1; + ctxt->markerSize = im*2; + } else if (markerstyle == 21) { + // full square + shape.resize(5); + shape[0].x = -im; shape[0].y = -im; + shape[1].x = im; shape[1].y = -im; + shape[2].x = im; shape[2].y = im; + shape[3].x = -im; shape[3].y = im; + shape[4].x = -im; shape[4].y = -im; + ctxt->markerType = 3; + } else if (markerstyle == 22) { + // full triangle up + shape.resize(4); + shape[0].x = -im; shape[0].y = im; + shape[1].x = im; shape[1].y = im; + shape[2].x = 0; shape[2].y = -im; + shape[3].x = -im; shape[3].y = im; + ctxt->markerType = 3; + } else if (markerstyle == 23) { + // full triangle down + shape.resize(4); + shape[0].x = 0; shape[0].y = im; + shape[1].x = im; shape[1].y = -im; + shape[2].x = -im; shape[2].y = -im; + shape[3].x = 0; shape[3].y = im; + ctxt->markerType = 3; + } else if (markerstyle == 25) { + // open square + shape.resize(5); + shape[0].x = -im; shape[0].y = -im; + shape[1].x = im; shape[1].y = -im; + shape[2].x = im; shape[2].y = im; + shape[3].x = -im; shape[3].y = im; + shape[4].x = -im; shape[4].y = -im; + ctxt->markerType = 2; + } else if (markerstyle == 26) { + // open triangle up + shape.resize(4); + shape[0].x = -im; shape[0].y = im; + shape[1].x = im; shape[1].y = im; + shape[2].x = 0; shape[2].y = -im; + shape[3].x = -im; shape[3].y = im; + ctxt->markerType = 2; + } else if (markerstyle == 27) { + // open losange + shape.resize(5); + Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5); + shape[0].x =-imx; shape[0].y = 0; + shape[1].x = 0; shape[1].y = -im; + shape[2].x = imx; shape[2].y = 0; + shape[3].x = 0; shape[3].y = im; + shape[4].x =-imx; shape[4].y = 0; + ctxt->markerType = 2; + } else if (markerstyle == 28) { + // open cross + shape.resize(13); + Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); + shape[0].x = -im; shape[0].y =-imx; + shape[1].x =-imx; shape[1].y =-imx; + shape[2].x =-imx; shape[2].y = -im; + shape[3].x = imx; shape[3].y = -im; + shape[4].x = imx; shape[4].y =-imx; + shape[5].x = im; shape[5].y =-imx; + shape[6].x = im; shape[6].y = imx; + shape[7].x = imx; shape[7].y = imx; + shape[8].x = imx; shape[8].y = im; + shape[9].x =-imx; shape[9].y = im; + shape[10].x=-imx; shape[10].y= imx; + shape[11].x= -im; shape[11].y= imx; + shape[12].x= -im; shape[12].y=-imx; + ctxt->markerType = 2; + } else if (markerstyle == 29) { + // full star pentagone + shape.resize(11); + Int_t im1 = Int_t(0.66*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.00*MarkerSizeReduced + 0.5); + Int_t im3 = Int_t(2.66*MarkerSizeReduced + 0.5); + Int_t im4 = Int_t(1.33*MarkerSizeReduced + 0.5); + shape[0].x = -im; shape[0].y = im4; + shape[1].x =-im2; shape[1].y =-im1; + shape[2].x =-im3; shape[2].y = -im; + shape[3].x = 0; shape[3].y =-im2; + shape[4].x = im3; shape[4].y = -im; + shape[5].x = im2; shape[5].y =-im1; + shape[6].x = im; shape[6].y = im4; + shape[7].x = im4; shape[7].y = im4; + shape[8].x = 0; shape[8].y = im; + shape[9].x =-im4; shape[9].y = im4; + shape[10].x= -im; shape[10].y= im4; + ctxt->markerType = 3; + } else if (markerstyle == 30) { + // open star pentagone + shape.resize(11); + Int_t im1 = Int_t(0.66*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.00*MarkerSizeReduced + 0.5); + Int_t im3 = Int_t(2.66*MarkerSizeReduced + 0.5); + Int_t im4 = Int_t(1.33*MarkerSizeReduced + 0.5); + shape[0].x = -im; shape[0].y = im4; + shape[1].x =-im2; shape[1].y =-im1; + shape[2].x =-im3; shape[2].y = -im; + shape[3].x = 0; shape[3].y =-im2; + shape[4].x = im3; shape[4].y = -im; + shape[5].x = im2; shape[5].y =-im1; + shape[6].x = im; shape[6].y = im4; + shape[7].x = im4; shape[7].y = im4; + shape[8].x = 0; shape[8].y = im; + shape[9].x =-im4; shape[9].y = im4; + shape[10].x= -im; shape[10].y= im4; + ctxt->markerType = 2; + } else if (markerstyle == 32) { + // open triangle down + shape.resize(4); + shape[0].x = 0; shape[0].y = im; + shape[1].x = im; shape[1].y = -im; + shape[2].x = -im; shape[2].y = -im; + shape[3].x = 0; shape[3].y = im; + ctxt->markerType = 2; + } else if (markerstyle == 33) { + // full losange + shape.resize(5); + Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5); + shape[0].x =-imx; shape[0].y = 0; + shape[1].x = 0; shape[1].y = -im; + shape[2].x = imx; shape[2].y = 0; + shape[3].x = 0; shape[3].y = im; + shape[4].x =-imx; shape[4].y = 0; + ctxt->markerType = 3; + } else if (markerstyle == 34) { + // full cross + shape.resize(13); + Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); + shape[0].x = -im; shape[0].y =-imx; + shape[1].x =-imx; shape[1].y =-imx; + shape[2].x =-imx; shape[2].y = -im; + shape[3].x = imx; shape[3].y = -im; + shape[4].x = imx; shape[4].y =-imx; + shape[5].x = im; shape[5].y =-imx; + shape[6].x = im; shape[6].y = imx; + shape[7].x = imx; shape[7].y = imx; + shape[8].x = imx; shape[8].y = im; + shape[9].x =-imx; shape[9].y = im; + shape[10].x=-imx; shape[10].y= imx; + shape[11].x= -im; shape[11].y= imx; + shape[12].x= -im; shape[12].y=-imx; + ctxt->markerType = 3; + } else if (markerstyle == 35) { + // diamond with cross + shape.resize(8); + shape[0].x =-im; shape[0].y = 0; + shape[1].x = 0; shape[1].y = -im; + shape[2].x = im; shape[2].y = 0; + shape[3].x = 0; shape[3].y = im; + shape[4].x =-im; shape[4].y = 0; + shape[5].x = im; shape[5].y = 0; + shape[6].x = 0; shape[6].y = im; + shape[7].x = 0; shape[7].y =-im; + ctxt->markerType = 2; + } else if (markerstyle == 36) { + // square with diagonal cross + shape.resize(8); + shape[0].x = -im; shape[0].y = -im; + shape[1].x = im; shape[1].y = -im; + shape[2].x = im; shape[2].y = im; + shape[3].x = -im; shape[3].y = im; + shape[4].x = -im; shape[4].y = -im; + shape[5].x = im; shape[5].y = im; + shape[6].x = -im; shape[6].y = im; + shape[7].x = im; shape[7].y = -im; + ctxt->markerType = 2; + } else if (markerstyle == 37) { + // open three triangles + shape.resize(10); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = 0; + shape[1].x =-im2; shape[1].y = im; + shape[2].x = im2; shape[2].y = im; + shape[3].x = 0; shape[3].y = 0; + shape[4].x =-im2; shape[4].y = -im; + shape[5].x = -im; shape[5].y = 0; + shape[6].x = 0; shape[6].y = 0; + shape[7].x = im; shape[7].y = 0; + shape[8].x = im2; shape[8].y = -im; + shape[9].x = 0; shape[9].y = 0; + ctxt->markerType = 2; + } else if (markerstyle == 38) { + // + shaped marker with octagon + shape.resize(15); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = -im; shape[0].y = 0; + shape[1].x = -im; shape[1].y =-im2; + shape[2].x =-im2; shape[2].y = -im; + shape[3].x = im2; shape[3].y = -im; + shape[4].x = im; shape[4].y =-im2; + shape[5].x = im; shape[5].y = im2; + shape[6].x = im2; shape[6].y = im; + shape[7].x =-im2; shape[7].y = im; + shape[8].x = -im; shape[8].y = im2; + shape[9].x = -im; shape[9].y = 0; + shape[10].x = im; shape[10].y = 0; + shape[11].x = 0; shape[11].y = 0; + shape[12].x = 0; shape[12].y = -im; + shape[13].x = 0; shape[13].y = im; + shape[14].x = 0; shape[14].y = 0; + ctxt->markerType = 2; + } else if (markerstyle == 39) { + // filled three triangles + shape.resize(9); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = 0; + shape[1].x =-im2; shape[1].y = im; + shape[2].x = im2; shape[2].y = im; + shape[3].x = 0; shape[3].y = 0; + shape[4].x =-im2; shape[4].y = -im; + shape[5].x = -im; shape[5].y = 0; + shape[6].x = 0; shape[6].y = 0; + shape[7].x = im; shape[7].y = 0; + shape[8].x = im2; shape[8].y = -im; + ctxt->markerType = 3; + } else if (markerstyle == 40) { + // four open triangles X + shape.resize(13); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = 0; + shape[1].x = im2; shape[1].y = im; + shape[2].x = im; shape[2].y = im2; + shape[3].x = 0; shape[3].y = 0; + shape[4].x = im; shape[4].y = -im2; + shape[5].x = im2; shape[5].y = -im; + shape[6].x = 0; shape[6].y = 0; + shape[7].x = -im2; shape[7].y = -im; + shape[8].x = -im; shape[8].y = -im2; + shape[9].x = 0; shape[9].y = 0; + shape[10].x = -im; shape[10].y = im2; + shape[11].x = -im2; shape[11].y = im; + shape[12].x = 0; shape[12].y = 0; + ctxt->markerType = 2; + } else if (markerstyle == 41) { + // four filled triangles X + shape.resize(13); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = 0; + shape[1].x = im2; shape[1].y = im; + shape[2].x = im; shape[2].y = im2; + shape[3].x = 0; shape[3].y = 0; + shape[4].x = im; shape[4].y = -im2; + shape[5].x = im2; shape[5].y = -im; + shape[6].x = 0; shape[6].y = 0; + shape[7].x = -im2; shape[7].y = -im; + shape[8].x = -im; shape[8].y = -im2; + shape[9].x = 0; shape[9].y = 0; + shape[10].x = -im; shape[10].y = im2; + shape[11].x = -im2; shape[11].y = im; + shape[12].x = 0; shape[12].y = 0; + ctxt->markerType = 3; + } else if (markerstyle == 42) { + // open double diamonds + shape.resize(9); + Int_t imx = Int_t(MarkerSizeReduced + 0.5); + shape[0].x= 0; shape[0].y= im; + shape[1].x= -imx; shape[1].y= imx; + shape[2].x = -im; shape[2].y = 0; + shape[3].x = -imx; shape[3].y = -imx; + shape[4].x = 0; shape[4].y = -im; + shape[5].x = imx; shape[5].y = -imx; + shape[6].x = im; shape[6].y = 0; + shape[7].x= imx; shape[7].y= imx; + shape[8].x= 0; shape[8].y= im; + ctxt->markerType = 2; + } else if (markerstyle == 43) { + // filled double diamonds + shape.resize(9); + Int_t imx = Int_t(MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = im; + shape[1].x = -imx; shape[1].y = imx; + shape[2].x = -im; shape[2].y = 0; + shape[3].x = -imx; shape[3].y = -imx; + shape[4].x = 0; shape[4].y = -im; + shape[5].x = imx; shape[5].y = -imx; + shape[6].x = im; shape[6].y = 0; + shape[7].x = imx; shape[7].y = imx; + shape[8].x = 0; shape[8].y = im; + ctxt->markerType = 3; + } else if (markerstyle == 44) { + // open four triangles plus + shape.resize(11); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = 0; + shape[1].x = im2; shape[1].y = im; + shape[2].x = -im2; shape[2].y = im; + shape[3].x = im2; shape[3].y = -im; + shape[4].x = -im2; shape[4].y = -im; + shape[5].x = 0; shape[5].y = 0; + shape[6].x = im; shape[6].y = im2; + shape[7].x = im; shape[7].y = -im2; + shape[8].x = -im; shape[8].y = im2; + shape[9].x = -im; shape[9].y = -im2; + shape[10].x = 0; shape[10].y = 0; + ctxt->markerType = 2; + } else if (markerstyle == 45) { + // filled four triangles plus + shape.resize(13); + Int_t im0 = Int_t(0.4*MarkerSizeReduced + 0.5); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = im0; shape[0].y = im0; + shape[1].x = im2; shape[1].y = im; + shape[2].x = -im2; shape[2].y = im; + shape[3].x = -im0; shape[3].y = im0; + shape[4].x = -im; shape[4].y = im2; + shape[5].x = -im; shape[5].y = -im2; + shape[6].x = -im0; shape[6].y = -im0; + shape[7].x = -im2; shape[7].y = -im; + shape[8].x = im2; shape[8].y = -im; + shape[9].x = im0; shape[9].y = -im0; + shape[10].x = im; shape[10].y = -im2; + shape[11].x = im; shape[11].y = im2; + shape[12].x = im0; shape[12].y = im0; + ctxt->markerType = 3; + } else if (markerstyle == 46) { + // open four triangles X + shape.resize(13); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = im2; + shape[1].x = -im2; shape[1].y = im; + shape[2].x = -im; shape[2].y = im2; + shape[3].x = -im2; shape[3].y = 0; + shape[4].x = -im; shape[4].y = -im2; + shape[5].x = -im2; shape[5].y = -im; + shape[6].x = 0; shape[6].y = -im2; + shape[7].x = im2; shape[7].y = -im; + shape[8].x = im; shape[8].y = -im2; + shape[9].x = im2; shape[9].y = 0; + shape[10].x = im; shape[10].y = im2; + shape[11].x = im2; shape[11].y = im; + shape[12].x = 0; shape[12].y = im2; + ctxt->markerType = 2; + } else if (markerstyle == 47) { + // filled four triangles X + shape.resize(13); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = im2; + shape[1].x = -im2; shape[1].y = im; + shape[2].x = -im; shape[2].y = im2; + shape[3].x = -im2; shape[3].y = 0; + shape[4].x = -im; shape[4].y = -im2; + shape[5].x = -im2; shape[5].y = -im; + shape[6].x = 0; shape[6].y = -im2; + shape[7].x = im2; shape[7].y = -im; + shape[8].x = im; shape[8].y = -im2; + shape[9].x = im2; shape[9].y = 0; + shape[10].x = im; shape[10].y = im2; + shape[11].x = im2; shape[11].y = im; + shape[12].x = 0; shape[12].y = im2; + ctxt->markerType = 3; + } else if (markerstyle == 48) { + // four filled squares X + shape.resize(17); + Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5); + shape[0].x = 0; shape[0].y = im2*1.005; + shape[1].x = -im2; shape[1].y = im; + shape[2].x = -im; shape[2].y = im2; + shape[3].x = -im2; shape[3].y = 0; + shape[4].x = -im; shape[4].y = -im2; + shape[5].x = -im2; shape[5].y = -im; + shape[6].x = 0; shape[6].y = -im2; + shape[7].x = im2; shape[7].y = -im; + shape[8].x = im; shape[8].y = -im2; + shape[9].x = im2; shape[9].y = 0; + shape[10].x = im; shape[10].y = im2; + shape[11].x = im2; shape[11].y = im; + shape[12].x = 0; shape[12].y = im2*0.995; + shape[13].x = im2*0.995; shape[13].y = 0; + shape[14].x = 0; shape[14].y = -im2*0.995; + shape[15].x = -im2*0.995; shape[15].y = 0; + shape[16].x = 0; shape[16].y = im2*0.995; + ctxt->markerType = 3; + } else if (markerstyle == 49) { + // four filled squares plus + shape.resize(17); + Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5); + shape[0].x =-imx; shape[0].y =-imx*1.005; + shape[1].x =-imx; shape[1].y = -im; + shape[2].x = imx; shape[2].y = -im; + shape[3].x = imx; shape[3].y =-imx; + shape[4].x = im; shape[4].y =-imx; + shape[5].x = im; shape[5].y = imx; + shape[6].x = imx; shape[6].y = imx; + shape[7].x = imx; shape[7].y = im; + shape[8].x =-imx; shape[8].y = im; + shape[9].x =-imx; shape[9].y = imx; + shape[10].x = -im; shape[10].y = imx; + shape[11].x = -im; shape[11].y =-imx; + shape[12].x =-imx; shape[12].y =-imx*0.995; + shape[13].x =-imx; shape[13].y = imx; + shape[14].x = imx; shape[14].y = imx; + shape[15].x = imx; shape[15].y =-imx; + shape[16].x =-imx; shape[16].y =-imx*1.005; + ctxt->markerType = 3; } else { - Error("WriteGIF","cannot write file: %s",name); - i = 0; + // single dot + shape.resize(0); + ctxt->markerType = 0; + ctxt->markerSize = 0; } - delete [] red; - delete [] green; - delete [] blue; - return i; } -//////////////////////////////////////////////////////////////////////////////// -/// Draw image. - -void TGX11::PutImage(Int_t offset,Int_t itran,Int_t x0,Int_t y0,Int_t nx,Int_t ny,Int_t xmin, - Int_t ymin,Int_t xmax,Int_t ymax, UChar_t *image,Drawable_t wid) +void TGX11::SetAttText(WinContext_t wctxt, const TAttText &att) { - const int maxSegment = 20; - int i, n, x, y, xcur, x1, x2, y1, y2; - unsigned char *jimg, *jbase, icol; - int nlines[256]; - XSegment lines[256][maxSegment]; - Drawable_t id; - - if (wid) { - id = wid; - } else { - id = gCws->fDrawing; - } + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt) + return; - for (i = 0; i < 256; i++) nlines[i] = 0; + Int_t txalh = att.GetTextAlign() / 10; + Int_t txalv = att.GetTextAlign() % 10; - x1 = x0 + xmin; y1 = y0 + ny - ymax - 1; - x2 = x0 + xmax; y2 = y0 + ny - ymin - 1; - jbase = image + (ymin-1)*nx + xmin; + ctxt->textAlign = kAlignNone; - for (y = y2; y >= y1; y--) { - xcur = x1; jbase += nx; - for (jimg = jbase, icol = *jimg++, x = x1+1; x <= x2; jimg++, x++) { - if (icol != *jimg) { - if (icol != itran) { - n = nlines[icol]++; - lines[icol][n].x1 = xcur; lines[icol][n].y1 = y; - lines[icol][n].x2 = x-1; lines[icol][n].y2 = y; - if (nlines[icol] == maxSegment) { - SetColor(gGCline,(int)icol+offset); - XDrawSegments((Display*)fDisplay,id,*gGCline,&lines[icol][0], - maxSegment); - nlines[icol] = 0; - } - } - icol = *jimg; xcur = x; + switch (txalh) { + case 0 : + case 1 : + switch (txalv) { //left + case 1 : + ctxt->textAlign = kBLeft; //bottom + break; + case 2 : + ctxt->textAlign = kMLeft; //middle + break; + case 3 : + ctxt->textAlign = kTLeft; //top + break; } - } - if (icol != itran) { - n = nlines[icol]++; - lines[icol][n].x1 = xcur; lines[icol][n].y1 = y; - lines[icol][n].x2 = x-1; lines[icol][n].y2 = y; - if (nlines[icol] == maxSegment) { - SetColor(gGCline,(int)icol+offset); - XDrawSegments((Display*)fDisplay,id,*gGCline,&lines[icol][0], - maxSegment); - nlines[icol] = 0; + break; + case 2 : + switch (txalv) { //center + case 1 : + ctxt->textAlign = kBCenter; //bottom + break; + case 2 : + ctxt->textAlign = kMCenter; //middle + break; + case 3 : + ctxt->textAlign = kTCenter; //top + break; } - } - } - - for (i = 0; i < 256; i++) { - if (nlines[i] != 0) { - SetColor(gGCline,i+offset); - XDrawSegments((Display*)fDisplay,id,*gGCline,&lines[i][0],nlines[i]); - } + break; + case 3 : + switch (txalv) { //right + case 1 : + ctxt->textAlign = kBRight; //bottom + break; + case 2 : + ctxt->textAlign = kMRight; //center + break; + case 3 : + ctxt->textAlign = kTRight; //top + break; + } + break; } -} - -//////////////////////////////////////////////////////////////////////////////// -/// If id is NULL - loads the specified gif file at position [x0,y0] in the -/// current window. Otherwise creates pixmap from gif file - -Pixmap_t TGX11::ReadGIF(int x0, int y0, const char *file, Window_t id) -{ - FILE *fd; - Seek_t filesize = 0; - unsigned char *gifArr, *pixArr, red[256], green[256], blue[256], *j1, *j2, icol; - int i, j, k, width, height, ncolor, irep, offset; - float rr, gg, bb; - Pixmap_t pic = 0; - fd = fopen(file, "r"); - if (!fd) { - Error("ReadGIF", "unable to open GIF file"); - return pic; - } + SetColor(ctxt, &ctxt->fGClist[kGCtext], att.GetTextColor()); - fseek(fd, 0L, 2); - long ft = ftell(fd); - if (ft <=0) { - Error("ReadGIF", "unable to open GIF file"); - fclose(fd); - return pic; + XGCValues values; + if (XGetGCValues((Display*)fDisplay, ctxt->fGClist[kGCtext], GCForeground | GCBackground, &values)) { + XSetForeground( (Display*)fDisplay, ctxt->fGClist[kGCinvt], values.background ); + XSetBackground( (Display*)fDisplay, ctxt->fGClist[kGCinvt], values.foreground ); } else { - filesize = Seek_t(ft); - } - fseek(fd, 0L, 0); - - if (!(gifArr = (unsigned char *) calloc(filesize+256,1))) { - Error("ReadGIF", "unable to allocate array for gif"); - fclose(fd); - return pic; - } - - if (fread(gifArr, filesize, 1, fd) != 1) { - Error("ReadGIF", "GIF file read failed"); - free(gifArr); - fclose(fd); - return pic; - } - fclose(fd); - - irep = GIFinfo(gifArr, &width, &height, &ncolor); - if (irep != 0) { - free(gifArr); - return pic; - } - - if (!(pixArr = (unsigned char *) calloc((width*height),1))) { - Error("ReadGIF", "unable to allocate array for image"); - free(gifArr); - return pic; - } - - irep = GIFdecode(gifArr, pixArr, &width, &height, &ncolor, red, green, blue); - if (irep != 0) { - free(gifArr); - free(pixArr); - return pic; - } - - // S E T P A L E T T E - - offset = 8; - - for (i = 0; i < ncolor; i++) { - rr = red[i]/255.; - gg = green[i]/255.; - bb = blue[i]/255.; - j = i+offset; - SetRGB(j,rr,gg,bb); + Error("SetAttText", "cannot get GC values"); } + XSetBackground((Display*)fDisplay, ctxt->fGClist[kGCtext], GetColor(0).fPixel); - // O U T P U T I M A G E - - for (i = 1; i <= height/2; i++) { - j1 = pixArr + (i-1)*width; - j2 = pixArr + (height-i)*width; - for (k = 0; k < width; k++) { - icol = *j1; *j1++ = *j2; *j2++ = icol; + // use first existing font + for (int i = 0; i < kMAXFONT; i++) + if (gFont[i].id) { + gCws->textFont = gFont[i].id; + XSetFont((Display*)fDisplay, gCws->fGClist[kGCtext], gCws->textFont->fid); + XSetFont((Display*)fDisplay, gCws->fGClist[kGCinvt], gCws->textFont->fid); + break; } - } - if (id) pic = CreatePixmap(id, width, height); - PutImage(offset,-1,x0,y0,width,height,0,0,width-1,height-1,pixArr,pic); - - free(gifArr); - free(pixArr); - - if (pic) - return pic; - else if (gCws->fDrawing) - return (Pixmap_t)gCws->fDrawing; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Returns an array of pixels created from a part of drawable -/// (defined by x, y, w, h) in format: -/// `b1, g1, r1, 0, b2, g2, r2, 0, ..., bn, gn, rn, 0`. -/// -/// Pixels are numbered from left to right and from top to bottom. -/// By default all pixels from the whole drawable are returned. -/// -/// Note that return array is 32-bit aligned - -unsigned char *TGX11::GetColorBits(Drawable_t /*wid*/, Int_t /*x*/, Int_t /*y*/, - UInt_t /*w*/, UInt_t /*h*/) -{ - return nullptr; -} - -//////////////////////////////////////////////////////////////////////////////// -/// create pixmap from RGB data. RGB data is in format : -/// b1, g1, r1, 0, b2, g2, r2, 0 ... bn, gn, rn, 0 .. -/// -/// Pixels are numbered from left to right and from top to bottom. -/// Note that data must be 32-bit aligned -Pixmap_t TGX11::CreatePixmapFromData(unsigned char * /*bits*/, UInt_t /*width*/, - UInt_t /*height*/) -{ - return (Pixmap_t)0; + ctxt->fAttText = att; } //////////////////////////////////////////////////////////////////////////////// -/// Register pixmap created by gVirtualGL -/// -/// \param [in] pixid Pixmap identifier -/// \param [in] w,h Width and height of the pixmap -/// -/// register new pixmap +/// Set window draw mode -Int_t TGX11::AddPixmap(ULong_t pixid, UInt_t w, UInt_t h) +void TGX11::SetDrawModeW(WinContext_t wctxt, EDrawMode mode) { - Int_t wid = 0; - - // Select next free window number - for (; wid < fMaxNumberOfWindows; ++wid) - if (!fWindows[wid].fOpen) - break; - - if (wid == fMaxNumberOfWindows) { - Int_t newsize = fMaxNumberOfWindows + 10; - fWindows = (XWindow_t*) TStorage::ReAlloc( - fWindows, newsize * sizeof(XWindow_t), - fMaxNumberOfWindows*sizeof(XWindow_t) - ); - - for (Int_t i = fMaxNumberOfWindows; i < newsize; ++i) - fWindows[i].fOpen = 0; + fDrawMode = mode; - fMaxNumberOfWindows = newsize; - } + auto ctxt = (XWindow_t *) wctxt; + if (!ctxt || !fDisplay) + return; - fWindows[wid].fOpen = 1; - gCws = fWindows + wid; - gCws->fWindow = pixid; - gCws->fDrawing = gCws->fWindow; - gCws->fBuffer = 0; - gCws->fDoubleBuffer = 0; - gCws->fIsPixmap = 1; - gCws->fClip = 0; - gCws->fWidth = w; - gCws->fHeight = h; - gCws->fNewColors = nullptr; - gCws->fShared = kFALSE; + auto gxmode = GXcopy; + if (mode == kXor) + gxmode = GXxor; + else if (mode == kInvert) + gxmode = GXinvert; + for (int i = 0; i < kMAXGC; i++) + XSetFunction((Display*)fDisplay, ctxt->fGClist[i], gxmode); - return wid; + ctxt->drawMode = mode; } //////////////////////////////////////////////////////////////////////////////// -/// Returns 1 if window system server supports extension given by the -/// argument, returns 0 in case extension is not supported and returns -1 -/// in case of error (like server not initialized). -/// Examples: -/// - "Apple-WM" - does server run on MacOS X; -/// - "XINERAMA" - does server support Xinerama. -/// See also the output of xdpyinfo. +/// Returns window draw mode -Int_t TGX11::SupportsExtension(const char *ext) const +TVirtualX::EDrawMode TGX11::GetDrawModeW(WinContext_t wctxt) { - Int_t major_opcode, first_event, first_error; - if (!(Display*)fDisplay) - return -1; - return XQueryExtension((Display*)fDisplay, ext, &major_opcode, &first_event, &first_error); + auto ctxt = (XWindow_t *) wctxt; + return ctxt ? ctxt->drawMode : kCopy; } diff --git a/graf2d/x11ttf/CMakeLists.txt b/graf2d/x11ttf/CMakeLists.txt index cd8a77bd07867..dc0902cd941f8 100644 --- a/graf2d/x11ttf/CMakeLists.txt +++ b/graf2d/x11ttf/CMakeLists.txt @@ -20,7 +20,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(GX11TTF ${X11_LIBRARIES} ${X11_Xpm_LIB} ${X11_Xft_LIB} - ${FREETYPE_LIBRARIES} + Freetype::Freetype ZLIB::ZLIB ${CMAKE_THREAD_LIBS_INIT} DEPENDENCIES @@ -28,4 +28,4 @@ ROOT_STANDARD_LIBRARY_PACKAGE(GX11TTF Graf ) -target_include_directories(GX11TTF PRIVATE ${FREETYPE_INCLUDE_DIRS} ${X11_INCLUDE_DIR}) +target_include_directories(GX11TTF PRIVATE ${X11_INCLUDE_DIR}) diff --git a/graf2d/x11ttf/inc/TGX11TTF.h b/graf2d/x11ttf/inc/TGX11TTF.h index 99b4dbae09486..2309c0385d6d2 100644 --- a/graf2d/x11ttf/inc/TGX11TTF.h +++ b/graf2d/x11ttf/inc/TGX11TTF.h @@ -27,44 +27,36 @@ class TXftFontHash; class TGX11TTF : public TGX11 { private: - enum EAlign { -// clang++ (gVirtualX)) { - TGX11 *oldg = (TGX11 *) gVirtualX; - gVirtualX = new TGX11TTF(*oldg); + if (auto oldg = dynamic_cast(gVirtualX)) { + gVirtualX = new TGX11TTF(std::move(*oldg)); delete oldg; } } @@ -209,9 +211,9 @@ Bool_t TGX11TTF::Init(void *display) /// then the rotation is applied on the alignment variables. /// SetRotation and LayoutGlyphs should have been called before. -void TGX11TTF::Align(void) +void TGX11TTF::Align(WinContext_t wctxt) { - EAlign align = (EAlign) fTextAlign; + auto align = GetTextAlignW(wctxt); // vertical alignment if (align == kTLeft || align == kTCenter || align == kTRight) { @@ -361,52 +363,52 @@ void TGX11TTF::DrawImage(FT_Bitmap *source, ULong_t fore, ULong_t back, //////////////////////////////////////////////////////////////////////////////// /// Draw text using TrueType fonts. If TrueType fonts are not available the -/// text is drawn with TGX11::DrawText. +/// text is drawn with TGX11::DrawTextW. -void TGX11TTF::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, - const char *text, ETextMode mode) +void TGX11TTF::DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const char *text, ETextMode mode) { if (!fHasTTFonts) { - TGX11::DrawText(x, y, angle, mgn, text, mode); + TGX11::DrawTextW(wctxt, x, y, angle, mgn, text, mode); } else { if (!TTF::fgInit) TTF::Init(); TTF::SetRotationMatrix(angle); TTF::PrepareString(text); TTF::LayoutGlyphs(); - Align(); - RenderString(x, y, mode); + Align(wctxt); + RenderString(wctxt, x, y, mode); } } //////////////////////////////////////////////////////////////////////////////// /// Draw text using TrueType fonts. If TrueType fonts are not available the -/// text is drawn with TGX11::DrawText. +/// text is drawn with TGX11::DrawTextW. -void TGX11TTF::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, - const wchar_t *text, ETextMode mode) +void TGX11TTF::DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, + const wchar_t *text, ETextMode mode) { if (!fHasTTFonts) { - TGX11::DrawText(x, y, angle, mgn, text, mode); + TGX11::DrawTextW(wctxt, x, y, angle, mgn, text, mode); } else { if (!TTF::fgInit) TTF::Init(); TTF::SetRotationMatrix(angle); TTF::PrepareString(text); TTF::LayoutGlyphs(); - Align(); - RenderString(x, y, mode); + Align(wctxt); + RenderString(wctxt, x, y, mode); } } //////////////////////////////////////////////////////////////////////////////// /// Get the background of the current window in an XImage. -RXImage *TGX11TTF::GetBackground(Int_t x, Int_t y, UInt_t w, UInt_t h) +RXImage *TGX11TTF::GetBackground(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h) { - Window_t cws = GetCurrentWindow(); + Window_t cws = GetWindow(wctxt); UInt_t width; UInt_t height; Int_t xy; - gVirtualX->GetWindowSize(cws, xy, xy, width, height); + GetWindowSize(cws, xy, xy, width, height); if (x < 0) { w += x; @@ -420,32 +422,37 @@ RXImage *TGX11TTF::GetBackground(Int_t x, Int_t y, UInt_t w, UInt_t h) if (x+w > width) w = width - x; if (y+h > height) h = height - y; - return (RXImage*)XGetImage((Display*)fDisplay, cws, x, y, w, h, AllPlanes, ZPixmap); + return (RXImage *)XGetImage((Display*)fDisplay, cws, x, y, w, h, AllPlanes, ZPixmap); } //////////////////////////////////////////////////////////////////////////////// /// Test if there is really something to render. -Bool_t TGX11TTF::IsVisible(Int_t x, Int_t y, UInt_t w, UInt_t h) +Bool_t TGX11TTF::IsVisible(WinContext_t wctxt, Int_t x, Int_t y, UInt_t w, UInt_t h) { - Window_t cws = GetCurrentWindow(); + Window_t cws = GetWindow(wctxt); UInt_t width; UInt_t height; Int_t xy; - gVirtualX->GetWindowSize(cws, xy, xy, width, height); + GetWindowSize(cws, xy, xy, width, height); // If w or h is 0, very likely the string is only blank characters - if ((int)w == 0 || (int)h == 0) return kFALSE; + if ((int)w == 0 || (int)h == 0) + return kFALSE; // If string falls outside window, there is probably no need to draw it. - if (x + (int)w <= 0 || x >= (int)width) return kFALSE; - if (y + (int)h <= 0 || y >= (int)height) return kFALSE; + if (x + (int)w <= 0 || x >= (int)width) + return kFALSE; + if (y + (int)h <= 0 || y >= (int)height) + return kFALSE; // If w or h are much larger than the window size, there is probably no need // to draw it. Moreover a to large text size may produce a Seg Fault in // malloc in RenderString. - if (w > 10*width) return kFALSE; - if (h > 10*height) return kFALSE; + if (w > 10*width) + return kFALSE; + if (h > 10*height) + return kFALSE; return kTRUE; } @@ -454,7 +461,7 @@ Bool_t TGX11TTF::IsVisible(Int_t x, Int_t y, UInt_t w, UInt_t h) /// Perform the string rendering in the pad. /// LayoutGlyphs should have been called before. -void TGX11TTF::RenderString(Int_t x, Int_t y, ETextMode mode) +void TGX11TTF::RenderString(WinContext_t wctxt, Int_t x, Int_t y, ETextMode mode) { TTF::TTGlyph* glyph = TTF::fgGlyphs; @@ -466,7 +473,8 @@ void TGX11TTF::RenderString(Int_t x, Int_t y, ETextMode mode) Int_t x1 = x-Xoff-fAlign.x; Int_t y1 = y+Yoff+fAlign.y-h; - if (!IsVisible(x1, y1, w, h)) return; + if (!IsVisible(wctxt, x1, y1, w, h)) + return; // create the XImage that will contain the text UInt_t depth = fDepth; @@ -482,9 +490,9 @@ void TGX11TTF::RenderString(Int_t x, Int_t y, ETextMode mode) ULong_t bg; XGCValues values; - GC *gc = (GC*)GetGC(3); + auto gc = (GC *) GetGCW(wctxt, 3); if (!gc) { - Error("DrawText", "error getting Graphics Context"); + Error("RenderString", "error getting Graphics Context"); return; } XGetGCValues((Display*)fDisplay, *gc, GCForeground | GCBackground, &values); @@ -492,7 +500,7 @@ void TGX11TTF::RenderString(Int_t x, Int_t y, ETextMode mode) // get the background if (mode == kClear) { // if mode == kClear we need to get an image of the background - XImage *bim = GetBackground(x1, y1, w, h); + XImage *bim = GetBackground(wctxt, x1, y1, w, h); if (!bim) { Error("DrawText", "error getting background image"); return; @@ -534,22 +542,25 @@ void TGX11TTF::RenderString(Int_t x, Int_t y, ETextMode mode) } // put the Ximage on the screen - Window_t cws = GetCurrentWindow(); - gc = (GC*)GetGC(6); - if (gc) XPutImage((Display*)fDisplay, cws, *gc, xim, 0, 0, x1, y1, w, h); + Window_t cws = GetWindow(wctxt); + gc = (GC *) GetGCW(wctxt, 6); + if (gc) + XPutImage((Display*)fDisplay, cws, *gc, xim, 0, 0, x1, y1, w, h); XDestroyImage(xim); } //////////////////////////////////////////////////////////////////////////////// /// Set specified font. -void TGX11TTF::SetTextFont(Font_t fontnumber) +void TGX11TTF::SetAttText(WinContext_t wctxt, const TAttText &att) { - fTextFont = fontnumber; - if (!fHasTTFonts) { - TGX11::SetTextFont(fontnumber); - } else { - TTF::SetTextFont(fontnumber); + // TODO: add to window context custom part for TTF, + // it can be allocated and provided via private interface + TGX11::SetAttText(wctxt, att); + + if (fHasTTFonts) { + TTF::SetTextFont(att.GetTextFont()); + TTF::SetTextSize(att.GetTextSize()); } } @@ -572,19 +583,6 @@ Int_t TGX11TTF::SetTextFont(char *fontname, ETextSetMode mode) } } -//////////////////////////////////////////////////////////////////////////////// -/// Set current text size. - -void TGX11TTF::SetTextSize(Float_t textsize) -{ - fTextSize = textsize; - if (!fHasTTFonts) { - TGX11::SetTextSize(textsize); - } else { - TTF::SetTextSize(textsize); - } -} - #ifdef R__HAS_XFT ///////////////////////////// Xft font methods ///////////////////////////////// @@ -604,6 +602,11 @@ FontStruct_t TGX11TTF::LoadQueryFont(const char *font_name) return (FontStruct_t)data->fXftFont; } + if (!gXftInit) { + XftInit(nullptr); + gXftInit = kTRUE; + } + XftFont *xftfont = XftFontOpenXlfd((Display*)fDisplay, fScreenNumber, font_name); data = new TXftFontData(0, xftfont, font_name); diff --git a/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx b/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx index 21c36c6a68228..3b3bfea8aa94a 100644 --- a/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx +++ b/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx @@ -82,6 +82,9 @@ public: const TBuffer3D& GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override; TBuffer3D *MakeBuffer3D() const override; + const std::vector &GetVertices() const { return fVertices; } + const std::vector &GetPolyDesc() const { return fPolyDesc; } + static void SetAutoEnforceTriangles(Bool_t f); static Bool_t GetAutoEnforceTriangles(); static void SetAutoCalculateNormals(Bool_t f); diff --git a/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx b/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx index 3163e28efb2a0..084e7821620f5 100644 --- a/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx +++ b/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx @@ -5,53 +5,177 @@ #include #include #include +#include "ROOT/REveSecondarySelectable.hxx" class TGeoNode; +class TGeoIterator; + namespace ROOT { namespace Experimental { +class REveGeoTopNodeData; +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeomDescription +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +class REveGeomDescription : public RGeomDescription { + static TGeoManager* s_geoManager; +protected: + std::vector fVisibilitySelf; + std::vector fVisibilityRec; + + virtual void RefineGeoItem(ROOT::RGeoItem &item, const std::vector &stack) override; + virtual bool IsFullModelStreamedAtOnce() const override { return false; } + + class Apex { + std::vector fPath; + TGeoNode *fNode{nullptr}; + + public: + void SetFromPath(std::vector absPath); + TGeoNode *LocateNodeWithPath(const std::vector &path) const; + + TGeoNode *GetNode() { return fNode; } + std::string GetFlatPath() const; + const std::vector& GetPath() const { return fPath; } + std::vector GetIndexStack() const; + }; -class REveGeoTopNodeData : public REveElement, - public REveAuntAsList + Apex fApex; + +public: + REveGeomDescription() : RGeomDescription() {}; + virtual ~REveGeomDescription() {}; + + enum ERnrFlags { + kRnrNone = 0, + kRnrSelf = 1, + kRnrChildren = 2 + }; + + bool ChangeEveVisibility(const std::vector &stack, ERnrFlags rnrFlag, bool on); + std::vector GetIndexStack() { return fApex.GetIndexStack(); } + const std::vector& GetApexPath() const { return fApex.GetPath();} + void InitPath(const std::vector& path); + TGeoNode* GetApexNode() { return fApex.GetNode(); } + TGeoNode* LocateNodeWithPath(const std::vector &path) { return fApex.LocateNodeWithPath(path); } + + bool GetVisiblityForStack(const std::vector& stack); + + void ImportFile(const char* filePath); + static TGeoManager* GetGeoManager(); +}; + +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeomHierarchy +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +class REveGeomHierarchy : public RGeomHierarchy { - friend class REveGeoTopNodeViz; + REveGeoTopNodeData* fReceiver{nullptr}; +protected: + virtual void WebWindowCallback(unsigned connid, const std::string &kind) override; + +public: + REveGeomHierarchy(REveGeomDescription &desc, bool th) : + RGeomHierarchy(desc, th){}; + + void SetReceiver(REveGeoTopNodeData* data) { fReceiver = data; } + virtual ~REveGeomHierarchy(){}; +}; + +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeoTopNodeData +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +class REveGeoTopNodeData : public REveElement, public REveAuntAsList { + friend class REveGeoTopNodeViz; +private: + std::shared_ptr fWebHierarchy; /// fWebHierarchy; ///& path); + void InitPath(const std::string& path); }; -//------------------------------------------------------------------- -class REveGeoTopNodeViz : public REveElement + +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeoTopNodeViz +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +class REveGeoTopNodeViz : public REveElement, + public REveSecondarySelectable { - private: +public: + enum EMode { + kModeNone, + kModeVisLevel, + kModeLeafOnly, + kModeMixed + }; + +private: + struct BShape { + TGeoShape *shape; + std::vector indices; + std::vector vertices; + }; + + struct BNode { + TGeoNode *node; + int shapeId; + int nodeId; + int color; + float trans[16]; + bool visible{true}; + }; + REveGeoTopNodeViz(const REveGeoTopNodeViz &) = delete; REveGeoTopNodeViz &operator=(const REveGeoTopNodeViz &) = delete; - REveGeoTopNodeData* fGeoData{nullptr}; + REveGeoTopNodeData *fGeoData{nullptr}; + std::vector fNodes; + std::vector fShapes; + EMode fMode{kModeVisLevel}; - public: + void CollectNodes(TGeoVolume *volume, std::vector &bnl, std::vector &browsables); + void CollectShapes(TGeoNode *node, std::set &shapes, std::vector &browsables); + bool AcceptNode(TGeoIterator& it, bool skip = true) const; + +public: REveGeoTopNodeViz(const Text_t *n = "REveGeoTopNodeViz", const Text_t *t = ""); - void SetGeoData(REveGeoTopNodeData* d) {fGeoData = d;} + void SetGeoData(REveGeoTopNodeData *d, bool rebuild = true); Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override; void BuildRenderData() override; + void GetIndicesFromBrowserStack(const std::vector &stack, std::set& outStack); + + void SetVisLevel(int); + void VisibilityChanged(bool on, REveGeomDescription::ERnrFlags flag, const std::vector& path); + void BuildDesc(); - bool RequiresExtraSelectionData() const override { return true; }; - void FillExtraSelectionData(nlohmann::json& j, const std::set& secondary_idcs) const override; + EMode GetVizMode() const { return fMode; } + void SetVizMode(EMode mode); using REveElement::GetHighlightTooltip; std::string GetHighlightTooltip(const std::set& secondary_idcs) const override; diff --git a/graf3d/eve7/src/REveGeoTopNode.cxx b/graf3d/eve7/src/REveGeoTopNode.cxx index 6778c077b9453..a49cf21f2e5fc 100644 --- a/graf3d/eve7/src/REveGeoTopNode.cxx +++ b/graf3d/eve7/src/REveGeoTopNode.cxx @@ -1,22 +1,35 @@ #include + +#include +#include + #include #include +#include #include +#include #include - +#include +#include +#include +#include "TBufferJSON.h" #include "TMath.h" + +#include "TGeoCompositeShape.h" #include "TGeoManager.h" #include "TClass.h" #include "TGeoNode.h" -#include "TGeoManager.h" +#include "TGeoMatrix.h" #include "TBase64.h" +#include "TStopwatch.h" + #include #include - +#include #include @@ -31,68 +44,351 @@ thread_local ElementId_t gSelId; #define REVEGEO_DEBUG_PRINT(fmt, ...) #endif -//////////////////////////////////////////////////////////////////////////////// -/// Constructor. -REveGeoTopNodeData::REveGeoTopNodeData(const Text_t *n, const Text_t *t) : REveElement(n, t) +TGeoManager* REveGeomDescription::s_geoManager = nullptr; + +/* +namespace { +void PrintStackPath(const std::vector& stack) +{ + printf("Path: "); + + for (auto idx : stack) + printf("/%d", idx); + + printf("\n"); +} +}*/ + + +bool REveGeomDescription::ChangeEveVisibility(const std::vector &stack, ERnrFlags flags, bool on) { - fWebHierarchy = std::make_shared(fDesc, true); + std::vector &visVec = (flags == kRnrSelf) ? fVisibilitySelf : fVisibilityRec; + + for (auto iter = visVec.begin(); iter != visVec.end(); iter++) { + if (iter->stack == stack) { + // AMT TODO remove path fom the vsibilirt vector if it is true + iter->visible = on; + return true; + } + } + + visVec.emplace_back(stack, on); + return true; } -void REveGeoTopNodeData::SetTNode(TGeoNode *n) +void REveGeomDescription::RefineGeoItem(ROOT::RGeoItem &item, const std::vector &iStack) { - fGeoNode = n; - fDesc.Build(fGeoNode->GetVolume()); - fDesc.AddSignalHandler(this, [this](const std::string &kind) { ProcessSignal(kind); }); + std::vector stack = fApex.GetIndexStack(); + stack.insert(stack.end(), iStack.begin(), iStack.end()); + + auto isVisible = [&stack](std::vector &visVec) -> bool { + for (auto &visVecEl : visVec) { + /* + printf("compare ======\n"); + PrintStackPath(stack); + PrintStackPath(visVecEl.stack); +*/ + if (stack == visVecEl.stack) + return visVecEl.visible ? 1 : 0; + } + return true; + }; + + int visSelf = isVisible(fVisibilitySelf); + int visRec = isVisible(fVisibilityRec); + + item.SetLogicalVisibility(visRec); + item.SetPhysicalVisibility(visSelf); + + //return RGeoItem(node.name, node.chlds.size(), node.id, node.color, node.material, + // visRec, vis); } + +void REveGeomDescription::InitPath(const std::vector& path) +{ + fApex.SetFromPath(path); + Build(fApex.GetNode()->GetVolume()); // rebuild geo-webviewer +} + +bool REveGeomDescription::GetVisiblityForStack(const std::vector &nodeStack) +{ + // visibility self + for (auto &visVecEl : fVisibilitySelf) { + if (nodeStack == visVecEl.stack) { + return false; + } + } + + // visibility recurse/children + for (auto &visVecEl : fVisibilityRec) { + bool inside = + nodeStack.size() >= visVecEl.stack.size() && std::equal(visVecEl.stack.begin(), visVecEl.stack.end(), nodeStack.begin()); + if (inside) + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////////////////// +/// Table signal handling -void REveGeoTopNodeData::SetChannel(unsigned connid, int chid) +void REveGeomHierarchy::WebWindowCallback(unsigned connid, const std::string &arg) { - fWebHierarchy->Show({gEve->GetWebWindow(), connid, chid}); + using namespace std::string_literals; + REveGeomDescription &eveDesc = dynamic_cast(fDesc); + + REveGeoManagerHolder gmgr(REveGeomDescription::GetGeoManager()); + if (arg.compare(0, 6, "CDTOP:") == 0) + { + std::vector ep; + eveDesc.InitPath(ep); + fDesc.IssueSignal(this, "CdTop"); + fWebWindow->Send(connid, "RELOAD"s); + } + else if (arg.compare(0, 5, "CDUP:") == 0) + { + std::vector result = eveDesc.GetApexPath(); + result.pop_back(); + eveDesc.InitPath(result); + fDesc.IssueSignal(this, "CdUp"); + fWebWindow->Send(connid, "RELOAD"s); + } + else if (arg.compare(0, 8, "SETAPEX:") == 0) { + auto path = TBufferJSON::FromJSON>(arg.substr(8)); + + //const std::vector &sstack = fDesc.GetSelectedStack(); + // std::vector sspath = fDesc.MakePathByStack(sstack); + std::vector result = eveDesc.GetApexPath(); + if (path->size() > 1) { + result.insert(result.end(), path->begin() + 1, path->end()); + eveDesc.InitPath(result); + fDesc.IssueSignal(this, "SelectTop"); + fWebWindow->Send(connid, "RELOAD"s); + } + } + else if ((arg.compare(0, 7, "SETVI0:") == 0) || (arg.compare(0, 7, "SETVI1:") == 0)) { + { + REveManager::ChangeGuard ch; + bool on = (arg[5] == '1'); + auto path = TBufferJSON::FromJSON>(arg.substr(7)); + // Get integer stack from string stack + std::vector base = eveDesc.GetIndexStack(); + std::vector stack = fDesc.MakeStackByPath(*path); + stack.insert(stack.begin(), base.begin(), base.end()); + + if (eveDesc.ChangeEveVisibility(stack, REveGeomDescription::kRnrChildren , on)) { + std::cout << "Set visibilty rnr CHIDLREN \n"; + fReceiver->VisibilityChanged(on, REveGeomDescription::kRnrChildren, stack); + } + } + } + else if ((arg.compare(0, 5, "SHOW:") == 0) || (arg.compare(0, 5, "HIDE:") == 0)) { + { + auto path = TBufferJSON::FromJSON>(arg.substr(5)); + bool on = (arg.compare(0, 5, "SHOW:") == 0); + // Get integer stack from string stack + + std::vector base = eveDesc.GetIndexStack(); + std::vector stack = fDesc.MakeStackByPath(*path); + stack.insert(stack.begin(), base.begin(), base.end()); + + if (path && eveDesc.ChangeEveVisibility(stack, REveGeomDescription::kRnrSelf, on)) { + std::cout << "Set visibilty rnr PHY \n"; + REveManager::ChangeGuard ch; + fReceiver->VisibilityChanged(on, REveGeomDescription::kRnrSelf, stack); + } + } + } + + else { + RGeomHierarchy::WebWindowCallback(connid, arg); + } } + //////////////////////////////////////////////////////////////////////////////// -namespace { -std::size_t getHash(std::vector &vec) +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +TGeoManager* REveGeomDescription::GetGeoManager() +{ + assert(s_geoManager); + return s_geoManager; +} + +void REveGeomDescription::Apex::SetFromPath(std::vector absPath) +{ + fPath = absPath; + fNode = LocateNodeWithPath(absPath); +} + +TGeoNode *REveGeomDescription::Apex::LocateNodeWithPath(const std::vector &path) const +{ + TGeoNode *top = REveGeomDescription::GetGeoManager()->GetTopNode(); + // printf("Top node name from geoData name (%s)\n", top->GetName()); + for (size_t t = 0; t < path.size(); t++) { + std::string s = path[t]; + std::cout << s << std::endl; + TGeoNode *ntop = top->GetVolume()->FindNode(s.c_str()); + if (!ntop) + throw std::runtime_error("Apex::LocateNodeWithPath(), can't locate node with path " + s); + top = ntop; + } + return top; +} + +std::string REveGeomDescription::Apex::GetFlatPath() const +{ + if (fPath.empty()) + return ""; + + std::ostringstream oss; + + oss << fPath[0]; + + for (size_t i = 1; i < fPath.size(); ++i) + oss << "/" << fPath[i]; + + return oss.str(); +} + +std::vector REveGeomDescription::Apex::GetIndexStack() const +{ + std::vector indexStack; + + TGeoNode* current = REveGeomDescription::GetGeoManager()->GetTopNode(); + + // optional: skip first if it is top itself + size_t start = 0; + std::vector nameStack = fPath; + if (!nameStack.empty() && nameStack[0] == current->GetName()) + start = 1; + + for (size_t i = start; i < nameStack.size(); ++i) + { + const std::string& targetName = nameStack[i]; + + TGeoVolume* vol = current->GetVolume(); + + int nd = vol->GetNdaughters(); + + int foundIndex = -1; + + for (int j = 0; j < nd; ++j) + { + TGeoNode* daughter = vol->GetNode(j); + + if (targetName == daughter->GetName()) + { + foundIndex = j; + current = daughter; + break; + } + } + + if (foundIndex == -1) + { + std::cerr << "Node not found: " << targetName << std::endl; + return {}; + } + + indexStack.push_back(foundIndex); + } + + // PrintStackPath(indexStack); + return indexStack; +} + +void REveGeomDescription::ImportFile(const char* filename) +{ + s_geoManager = TGeoManager::Import(filename); + if (!s_geoManager) { + throw std::runtime_error("Critical Error: Failed to import geometry file"); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// Constructor. + +REveGeoTopNodeData::REveGeoTopNodeData(const char* filename) +{ + // this below will be obsolete + fDesc.AddSignalHandler(this, [this](const std::string &kind) { ProcessSignal(kind); }); + fDesc.ImportFile(filename); + + + fWebHierarchy = std::make_shared(fDesc, true); + fWebHierarchy->SetReceiver(this); +} + +void REveGeoTopNodeData::InitPath(const std::string &path) +{ + std::regex re(R"([/\\]+)"); // split on one or more slashes + std::sregex_token_iterator it(path.begin(), path.end(), re, -1); + std::sregex_token_iterator end; + std::vector result; + + for (; it != end; ++it) { + if (!it->str().empty()) { // skip empty parts + result.push_back(*it); + } + } + + fDesc.InitPath(result); + + for (auto &el : fNieces) { + REveGeoTopNodeViz *etn = dynamic_cast(el); + etn->BuildDesc(); + } +} + +void REveGeoTopNodeData::VisibilityChanged(bool on, REveGeomDescription::ERnrFlags flag, const std::vector& path) { - std::size_t seed = vec.size(); - for (auto &x : vec) { - uint32_t i = (uint32_t)x; - seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2); + + for (auto &el : fNieces) { + REveGeoTopNodeViz *etn = dynamic_cast(el); + etn->VisibilityChanged(on, flag, path); } - return seed; } -} // namespace +//////////////////////////////////////////////////////////////////////////////// + +void REveGeoTopNodeData::SetChannel(unsigned connid, int chid) +{ + fWebHierarchy->Show({gEve->GetWebWindow(), connid, chid}); +} + +//////////////////////////////////////////////////////////////////////////////// void REveGeoTopNodeData::ProcessSignal(const std::string &kind) { REveManager::ChangeGuard ch; - if ((kind == "SelectTop") || (kind == "NodeVisibility")) { - StampObjProps(); - for (auto &n : fNieces) { - n->StampObjProps(); - } - } else if (kind == "HighlightItem") { - // printf("REveGeoTopNodeData element highlighted --------------------------------"); - auto sstack = fDesc.GetHighlightedItem(); - std::set ss; - ss.insert((int)getHash(sstack)); - for (auto &n : fNieces) { - gEve->GetHighlight()->NewElementPicked(n->GetElementId(), false, true, ss); + if ((kind == "SelectTop") || (kind == "CdTop") || (kind == "CdUp")) + { + for (auto &el : fNieces) { + REveGeoTopNodeViz *etn = dynamic_cast(el); + etn->BuildDesc(); } - gSelId = gEve->GetHighlight()->GetElementId(); + } + else if (kind == "HighlightItem") { + /* + printf("REveGeoTopNodeData element highlighted --------------------------------"\n); + */ } else if (kind == "ClickItem") { - // printf("REveGeoTopNodeData element selected --------------------------------"); + printf("REveGeoTopNodeData element CLICKED selected --------------------------------\n"); auto sstack = fDesc.GetClickedItem(); std::set ss; - ss.insert((int)getHash(sstack)); for (auto &n : fNieces) { - gEve->GetSelection()->NewElementPicked(n->GetElementId(), false, true, ss); + REveGeoTopNodeViz* viz = dynamic_cast(n); + viz->GetIndicesFromBrowserStack(sstack, ss); + bool multi = false; + bool secondary = true; + gEve->GetSelection()->NewElementPicked(n->GetElementId(), multi, secondary, ss); } - gSelId = gEve->GetSelection()->GetElementId(); } } @@ -103,90 +399,490 @@ Int_t REveGeoTopNodeData::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) { Int_t ret = REveElement::WriteCoreJson(j, rnr_offset); - if (!fGeoNode){ return ret;} return ret; } //////////////////////////////////////////////////////////////////////////////// +// REveGeoTopNodeViz //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -REveGeoTopNodeViz::REveGeoTopNodeViz(const Text_t *n, const Text_t *t) : REveElement(n, t) {} -std::string REveGeoTopNodeViz::GetHighlightTooltip(const std::set &) const +REveGeoTopNodeViz::REveGeoTopNodeViz(const Text_t *n, const Text_t *t) : REveElement(n, t) +{ + SetAlwaysSecSelect(true); +} + +void REveGeoTopNodeViz::SetVizMode(EMode mode) + { + fMode = mode; +} + +bool REveGeoTopNodeViz::AcceptNode(TGeoIterator &it, bool skip) const { - auto stack = fGeoData->fDesc.GetHighlightedItem(); - auto sa = fGeoData->fDesc.MakePathByStack(stack); - if (sa.empty()) + if (fMode == EMode::kModeVisLevel) + { + if (it.GetLevel() > fGeoData->fDesc.GetVisLevel()) { + it.Skip(); + return false; + } + } + else if (fMode == EMode::kModeLeafOnly) + { + // printf("accep mkod eleaf node ptr %p \n", (void*)it.GetNode(it.GetLevel())); + if (it.GetNode(it.GetLevel())->GetNdaughters()) + return false; + } + else if (fMode == EMode::kModeMixed) + { + if (it.GetLevel() > fGeoData->fDesc.GetVisLevel()) { + if (skip) it.Skip(); + return false; + } + // printf("accep mkod eleaf node ptr %p \n", (void*)it.GetNode(it.GetLevel())); + if (it.GetNode(it.GetLevel())->GetNdaughters()) + return false; + } + + return true; +} + +std::string REveGeoTopNodeViz::GetHighlightTooltip(const std::set & set) const +{ + REveGeoManagerHolder gmgr(REveGeomDescription::GetGeoManager()); + if (set.empty()) { return ""; - else { - std::string res; - size_t n = sa.size(); - for (size_t i = 0; i < n; ++i) { - res += sa[i]; - if (i < (n - 1)) - res += "/"; + } else { + auto it = set.begin(); + int pos = *it; + //const BNode &bn = fNodes[pos]; + std::cout << "highlight node with ID " << pos << "\n"; + + std::string res = "GeoNode name"; + + TGeoNode *top = fGeoData->fDesc.GetApexNode(); + TGeoIterator git(top->GetVolume()); + TGeoNode *node; + int i = 0; + TString path; + while ((node = git.Next())) + { + if (!AcceptNode(git)) + continue; + if (i == pos) { + git.GetPath(path); + res = path; + break; + } + i++; } return res; } } +void REveGeoTopNodeViz::BuildDesc() +{ + // locate top node + TGeoNode* top = fGeoData->fDesc.GetApexNode(); + + fNodes.clear(); + fShapes.clear(); + // shape array + std::set shapes; + TStopwatch timer; + timer.Start(); + CollectShapes(top, shapes, fShapes); + std::cout << "Shape size " << shapes.size() << "\n"; + + timer.Stop(); + + printf("Real time: %.3f s\n", timer.RealTime()); + printf("CPU time: %.3f s\n", timer.CpuTime()); + + // node array + timer.Start(); + CollectNodes(top->GetVolume(), fNodes, fShapes); + std::cout << "Node size " << fNodes.size() << "\n"; + + timer.Stop(); + + printf("NODES Real time: %.3f s\n", timer.RealTime()); + printf("NODES CPU time: %.3f s\n", timer.CpuTime()); + + StampObjProps(); +} + +void REveGeoTopNodeViz::CollectNodes(TGeoVolume *volume, std::vector &bnl, std::vector &browsables) +{ + printf("collect nodes \n"); + TGeoIterator it(volume); + TGeoNode *node; + int nodeId = 0; + + std::vector apexStack = fGeoData->RefDescription().GetIndexStack(); + + // get top node transformation + TGeoHMatrix global; + { + TGeoNode *inode = REveGeomDescription::GetGeoManager()->GetTopNode(); + for (int idx : apexStack) { + inode = inode->GetDaughter(idx); + global.Multiply(inode->GetMatrix()); + } + } + + while ((node = it.Next())) + { + if (!AcceptNode(it)) + continue; + + TGeoHMatrix full = global; // identity if global is identity + full.Multiply(it.GetCurrentMatrix()); + const TGeoMatrix *mat = &full; + + // const TGeoMatrix *mat = it.GetCurrentMatrix(); + const Double_t *t = mat->GetTranslation(); // size 3 + const Double_t *r = mat->GetRotationMatrix(); // size 9 (3x3) + + Double_t m[16]; + if (mat->IsScale()) { + const Double_t *s = mat->GetScale(); + m[0] = r[0] * s[0]; + m[1] = r[3] * s[0]; + m[2] = r[6] * s[0]; + m[3] = 0; + m[4] = r[1] * s[1]; + m[5] = r[4] * s[1]; + m[6] = r[7] * s[1]; + m[7] = 0; + m[8] = r[2] * s[2]; + m[9] = r[5] * s[2]; + m[10] = r[8] * s[2]; + m[11] = 0; + m[12] = t[0]; + m[13] = t[1]; + m[14] = t[2]; + m[15] = 1; + } else { + m[0] = r[0]; + m[1] = r[3]; + m[2] = r[6]; + m[3] = 0; + m[4] = r[1]; + m[5] = r[4]; + m[6] = r[7]; + m[7] = 0; + m[8] = r[2]; + m[9] = r[5]; + m[10] = r[8]; + m[11] = 0; + m[12] = t[0]; + m[13] = t[1]; + m[14] = t[2]; + m[15] = 1; + } + + BNode b; + b.node = node; + b.nodeId = nodeId; + b.color = node->GetVolume()->GetLineColor(); + + // TString path; it.GetPath(path); + // printf("[%d] %d %s \n", node->GetNdaughters(), it.GetLevel(), path.Data()); + + + // set BNode transformation matrix + for (int i = 0; i < 16; ++i) + b.trans[i] = m[i]; + + // find shape + TGeoShape *shape = node->GetVolume()->GetShape(); + b.shapeId = -1; // mark invalid at start + for (size_t i = 0; i < browsables.size(); i++) { + if (shape == browsables[i].shape) { + b.shapeId = i; + break; + } + } + assert(b.shapeId >= 0); + + + // set visibility flag + std::vector visStack = apexStack; + for (int i = 1; i <= it.GetLevel(); ++i) + visStack.push_back(it.GetIndex(i)); + // PrintStackPath(visStack); + b.visible = fGeoData->RefDescription().GetVisiblityForStack(visStack); + + // printf("Node %d shape id %d \n", (int)bnl.size(), b.shapeId); + bnl.push_back(b); + nodeId++; + + if (nodeId > 300000) { + R__LOG_ERROR(REveLog()) << "Max number of nodes reached ... breaking the loop \n"; + printf("num nodes locked !!! \n"); + break; + } + } +} + +void REveGeoTopNodeViz::CollectShapes(TGeoNode *tnode, std::set &shapes, std::vector &browsables) +{ + printf("collect shapes \n"); + TGeoIterator geoit(tnode->GetVolume()); + TGeoNode *node = nullptr; + while ((node = geoit.Next())) + { + if (!AcceptNode(geoit)) + continue; + + TGeoVolume *vol = node->GetVolume(); + if (vol) { + TGeoShape *shape = vol->GetShape(); + if (shape) { + auto it = shapes.find(shape); + if (it == shapes.end()) { + shapes.insert(shape); // use set to avoid duplicates + REveGeoPolyShape polyShape; + TGeoCompositeShape *compositeShape = dynamic_cast(shape); + int n_seg = 60; // default value in the geo manager and poly shape + if (compositeShape) + polyShape.BuildFromComposite(compositeShape, n_seg); + else + polyShape.BuildFromShape(shape, n_seg); + + // printf("[%d] Shape name %s %s \n",(int)browsables.size(), shape->GetName(), shape->ClassName()); + + // printf("vertices %lu: \n", polyShape.fVertices.size()); + + // create browser shape + BShape browserShape; + browserShape.shape = shape; + browsables.push_back(browserShape); + + // copy vertices transform vec double to float + browsables.back().vertices.reserve(polyShape.GetVertices().size()); + for (size_t i = 0; i < polyShape.GetVertices().size(); i++) + browsables.back().vertices.push_back(polyShape.GetVertices()[i]); + + // copy indices kip the first integer in the sequence of 4 + for (size_t i = 0; i < polyShape.GetPolyDesc().size(); i += 4) { + browsables.back().indices.push_back(polyShape.GetPolyDesc()[i + 1]); + browsables.back().indices.push_back(polyShape.GetPolyDesc()[i + 2]); + browsables.back().indices.push_back(polyShape.GetPolyDesc()[i + 3]); + } + // printf("last browsable size indices size %lu \n", browsables.back().indices.size()); + } + } + } + } +} + void REveGeoTopNodeViz::BuildRenderData() { fRenderData = std::make_unique("makeGeoTopNode"); + for (size_t i = 0; i < fNodes.size(); ++i) { + + UChar_t c[4] = {1, 2, 3, 4}; + REveUtil::ColorFromIdx(fNodes[i].color, c); + // if (i < 400) printf("%d > %d %d %d %d \n",fNodes[i].color, c[0], c[1], c[2], c[3]); + uint32_t v = (c[0] << 16) + (c[1] << 8) + c[2]; + float pc; + std::memcpy(&pc, &v, sizeof(pc)); + GetRenderData()->PushV(pc); + } +} +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void REveGeoTopNodeViz::SetGeoData(REveGeoTopNodeData *d, bool rebuild) +{ + fGeoData = d; + if (rebuild) + BuildDesc(); } +//------------------------------------------------------------------------------ + int REveGeoTopNodeViz::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) { + REveGeoManagerHolder gmgr(REveGeomDescription::GetGeoManager()); Int_t ret = REveElement::WriteCoreJson(j, rnr_offset); + if (!fGeoData) { j["dataId"] = -1; } else { - std::string json = fGeoData->fDesc.ProduceJson(); - j["geomDescription"] = TBase64::Encode(json.c_str()); - printf("REveGeoTopNodeViz::WriteCoreJson stream geomDescription json size = %ld\n", (long) json.size()); + // std::string json = fGeoData->fDesc.ProduceJson(); + // j["geomDescription"] = TBase64::Encode(json.c_str()); j["dataId"] = fGeoData->GetElementId(); } + j["visLevel"] = fGeoData ? fGeoData->fDesc.GetVisLevel() : 0; + + // put shapes vector in json array + using namespace nlohmann; + + json shapeVertexArr = json::array(); + int vertexOff = 0; + + json shapeIndexArr = json::array(); + json shapePolySizeArr = json::array(); + json shapePolyOffArr = json::array(); + + json nodeVisibility = json::array(); + + int polyOff = 0; + + // need four integers for + for (size_t i = 0; i < fShapes.size(); ++i) { + // vertices + + std::copy(fShapes[i].vertices.begin(), fShapes[i].vertices.end(), std::back_inserter(shapeVertexArr)); + + int numVertices = int(fShapes[i].vertices.size()); + // indices + // write shape indices with the vertexOff + for (size_t p = 0; p < fShapes[i].indices.size(); ++p) + shapeIndexArr.push_back(fShapes[i].indices[p] + vertexOff); + + int numIndices = int(fShapes[i].indices.size()); + shapePolySizeArr.push_back(numIndices); + shapePolyOffArr.push_back(polyOff); + + // printf("shape [%d] numIndices %d \n", i, numIndices); + + polyOff += numIndices; + vertexOff += numVertices / 3; + } + + // write vector of shape ids for visible nodes + json nodeShapeIds = json::array(); + json nodeTrans = json::array(); + json nodeColors = json::array(); + + for (size_t i = 0; i < fNodes.size(); ++i) { + nodeShapeIds.push_back(fNodes[i].shapeId); + nodeVisibility.push_back(fNodes[i].visible); + for (int t = 0; t < 16; t++) + nodeTrans.push_back(fNodes[i].trans[t]); + } + // shape basic array + + j["shapeVertices"] = shapeVertexArr; + + // shape basic indices array + j["shapeIndices"] = shapeIndexArr; + + // shape poly offset array + j["shapeIndicesOff"] = shapePolyOffArr; + j["shapeIndicesSize"] = shapePolySizeArr; + + j["nodeShapeIds"] = nodeShapeIds; + j["nodeTrans"] = nodeTrans; + j["nodeVisibility"] = nodeVisibility; + j["fSecondarySelect"] = fAlwaysSecSelect; + + + + + // ship bounding box info + TGeoNode* top = fGeoData->fDesc.GetApexNode(); + TGeoVolume *vol = top->GetVolume(); + TGeoShape *shape = vol->GetShape(); + shape->ComputeBBox(); + TGeoBBox *box = dynamic_cast(shape); + if (box) { + const Double_t *origin = box->GetOrigin(); + + printf("BBox center: (%f, %f, %f)\n", origin[0], origin[1], origin[2]); + //printf("origin lengths: (%f, %f, %f)\n", origin[0], origin[1], origin[2]); + + auto jbb = json::array(); + jbb.push_back(origin[0] - box->GetDX()); + jbb.push_back(origin[0] + box->GetDX()); + jbb.push_back(origin[1] - box->GetDY()); + jbb.push_back(origin[1] + box->GetDY()); + jbb.push_back(origin[2] - box->GetDZ()); + jbb.push_back(origin[2] + box->GetDZ()); + j["bbox"] = jbb; + } + // std::cout << "Write Core json " << j.dump(1) << "\n"; return ret; } -void REveGeoTopNodeViz::FillExtraSelectionData(nlohmann::json &j, const std::set &) const +void REveGeoTopNodeViz::SetVisLevel(int vl) { - j["stack"] = nlohmann::json::array(); - std::vector stack; - if (gSelId == gEve->GetHighlight()->GetElementId()) - stack = fGeoData->fDesc.GetHighlightedItem(); - else if (gSelId == gEve->GetSelection()->GetElementId()) - stack = fGeoData->fDesc.GetClickedItem(); + if (fGeoData) { + fGeoData->fDesc.SetVisLevel(vl); + StampObjProps(); + } +} - if (stack.empty()) - return; +void REveGeoTopNodeViz::GetIndicesFromBrowserStack(const std::vector &stack, std::set &res) +{ + TGeoNode *top = fGeoData->fDesc.GetApexNode(); + TGeoIterator it(top->GetVolume()); + std::vector nodeStack; + int cnt = 0; + TGeoNode *node; -#ifdef REVEGEO_DEBUG - printf("cicked stack: "); - for (auto i : stack) - printf(" %d, ", i); - printf("\n"); -#endif + while ((node = it.Next())) { + int level = it.GetLevel(); - for (auto i : stack) - j["stack"].push_back(i); + bool accept = AcceptNode(it, false); + nodeStack.resize(level); + if (level > 0) + nodeStack[level - 1] = it.GetIndex(level); -#ifdef REVEGEO_DEBUG - printf("extra stack: "); - int ss = j["stack"].size(); - for (int i = 0; i < ss; ++i) { - int d = j["stack"][i]; - printf(" %d,", d); - } - printf("----\n"); - auto ids = fGeoData->fDesc.MakeIdsByStack(stack); - printf("node ids from stack: "); - for (auto i : ids) - printf(" %d, ", i); - printf("\n"); + bool inside = nodeStack.size() >= stack.size() && std::equal(stack.begin(), stack.end(), nodeStack.begin()); + if (inside) { + res.insert(cnt); + } // rnr flags + if (accept) cnt++; + } // while it - int id = fGeoData->fDesc.FindNodeId(stack); - printf("NODE ID %d\n", id); -#endif + printf("GetIndicesFromBrowserStack stack size %zu res size %zu\n", stack.size(), res.size()); } + +void REveGeoTopNodeViz::VisibilityChanged(bool on, REveGeomDescription::ERnrFlags flag, const std::vector &iStack) +{ + // function argument is full stack, we remove the apex path + size_t apexDepth = fGeoData->RefDescription().GetApexPath().size(); + std::vector stack(iStack.begin() + apexDepth, iStack.end()); + + // PrintStackPath(stack); + + TGeoNode *top = fGeoData->fDesc.GetApexNode(); + TGeoIterator it(top->GetVolume()); + std::vector nodeStack; + int cnt = 0; + TGeoNode *node; + while ((node = it.Next())) { + + int level = it.GetLevel(); + if (!AcceptNode(it)) + continue; + + nodeStack.resize(level); + if (level > 0) + nodeStack[level - 1] = it.GetIndex(level); + + if (flag == REveGeomDescription::kRnrSelf) { + /* + printf("nODEcompare ======\n"); + PrintStackPath(stack); + PrintStackPath(nodeStack); + */ + if (nodeStack == stack) { + fNodes[cnt].visible = on; + + break; + } + } else { + bool inside = nodeStack.size() >= stack.size() && std::equal(stack.begin(), stack.end(), nodeStack.begin()); + if (inside) { + fNodes[cnt].visible = on; + } + } // rnr flags + cnt++; + } // while it + StampObjProps(); +} \ No newline at end of file diff --git a/graf3d/ftgl/CMakeLists.txt b/graf3d/ftgl/CMakeLists.txt index 92ee0bb663648..2aeb51f5d7ab3 100644 --- a/graf3d/ftgl/CMakeLists.txt +++ b/graf3d/ftgl/CMakeLists.txt @@ -38,16 +38,19 @@ ROOT_LINKER_LIBRARY(FTGL LIBRARIES OpenGL::GL OpenGL::GLU - ${FREETYPE_LIBRARIES} + Freetype::Freetype ZLIB::ZLIB BUILTINS FREETYPE ) target_include_directories(FTGL PRIVATE - ${FREETYPE_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/graf3d/gl/inc ) +if(builtin_freetype) + add_dependencies(FTGL BUILTIN_FREETYPE) +endif() + ROOT_INSTALL_HEADERS() diff --git a/graf3d/gl/CMakeLists.txt b/graf3d/gl/CMakeLists.txt index 4bf49d6d07f08..8fa7eec0c9bbd 100644 --- a/graf3d/gl/CMakeLists.txt +++ b/graf3d/gl/CMakeLists.txt @@ -17,11 +17,6 @@ if(x11) set(RGL_EXTRA_SOURCES TX11GL.cxx) endif() - -if(builtin_gl2ps) - set(RGL_EXTRA_SOURCES ${RGL_EXTRA_SOURCES} src/gl2ps.cxx) -endif() - set_source_files_properties(src/TGLFontManager.cxx PROPERTIES COMPILE_FLAGS "${FTGL_CFLAGS}") set_source_files_properties(src/TGLText.cxx PROPERTIES COMPILE_FLAGS "${FTGL_CFLAGS}") @@ -208,7 +203,9 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RGL OpenGL::GL OpenGL::GLU ${FTGL_LIBRARIES} - ${GL2PS_LIBRARIES} + gl2ps::gl2ps + Freetype::Freetype + ZLIB::ZLIB ${X11_LIBRARIES} ROOTGlad DEPENDENCIES @@ -221,19 +218,12 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RGL ${installoptions} ) + target_include_directories(RGL PRIVATE ${OPENGL_INCLUDE_DIR} ${FTGL_INCLUDE_DIR} - ${FREETYPE_INCLUDE_DIRS} - ${GLEW_INCLUDE_DIRS} ) -if(builtin_gl2ps) - target_include_directories(RGL PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/gl2ps) -else() - target_include_directories(RGL PRIVATE ${GL2PS_INCLUDE_DIRS}) -endif() - if(MACOSX_GLU_DEPRECATED) target_compile_options(RGL PRIVATE -Wno-deprecated-declarations) endif() diff --git a/graf3d/gl/inc/TGLFontManager.h b/graf3d/gl/inc/TGLFontManager.h index 83a56a45986ad..844230a305d34 100644 --- a/graf3d/gl/inc/TGLFontManager.h +++ b/graf3d/gl/inc/TGLFontManager.h @@ -48,6 +48,7 @@ class TGLFont Int_t fSize; // free-type face size Int_t fFile; // free-type file name EMode fMode; // free-type FTGL class id + UInt_t fTextAlign = 0; // set text align mutable Int_t fTrashCount; public: @@ -74,6 +75,8 @@ class TGLFont Float_t GetDepth() const { return fDepth; } void SetDepth(Float_t d) { fDepth = d; } + void SetTextAlign(UInt_t align) { fTextAlign = align; } + // FTGL wrapper functions Float_t GetAscent() const; Float_t GetDescent() const; diff --git a/graf3d/gl/inc/TGLPadPainter.h b/graf3d/gl/inc/TGLPadPainter.h index d09646ed9c705..57426b6e3e27e 100644 --- a/graf3d/gl/inc/TGLPadPainter.h +++ b/graf3d/gl/inc/TGLPadPainter.h @@ -12,10 +12,11 @@ #ifndef ROOT_TGLPadPainter #define ROOT_TGLPadPainter -#include "TVirtualPadPainter.h" +#include "TPadPainterBase.h" #include "TGLFontManager.h" #include "TGLPadUtils.h" #include "TPoint.h" +#include "GuiTypes.h" #include @@ -25,13 +26,15 @@ class TRadialGradient; The _main_ purpose of TGLPadPainter is to enable 2d gl raphics inside standard TPad/TCanvas. */ -class TGLPadPainter : public TVirtualPadPainter { +class TGLPadPainter : public TPadPainterBase { private: Rgl::Pad::PolygonStippleSet fSSet; Rgl::Pad::Tesselator fTess; Rgl::Pad::MarkerPainter fMarker; Rgl::Pad::GLLimits fLimits; + WinContext_t fWinContext; // context of selected drawable + std::vector fVs;//Vertex buffer for tesselator. TGLFontManager fFM; @@ -49,49 +52,17 @@ class TGLPadPainter : public TVirtualPadPainter { public: TGLPadPainter(); - //Final overriders for TVirtualPadPainter pure virtual functions. - //1. Part, which simply delegates to TVirtualX. - //Line attributes. - Color_t GetLineColor() const override; - Style_t GetLineStyle() const override; - Width_t GetLineWidth() const override; - - void SetLineColor(Color_t lcolor) override; - void SetLineStyle(Style_t lstyle) override; - void SetLineWidth(Width_t lwidth) override; - - //Fill attributes. - Color_t GetFillColor() const override; - Style_t GetFillStyle() const override; - Bool_t IsTransparent() const override; - - void SetFillColor(Color_t fcolor) override; - void SetFillStyle(Style_t fstyle) override; void SetOpacity(Int_t percent) override; - - //Text attributes. - Short_t GetTextAlign() const override; - Float_t GetTextAngle() const override; - Color_t GetTextColor() const override; - Font_t GetTextFont() const override; - Float_t GetTextSize() const override; Float_t GetTextMagnitude() const override; - void SetTextAlign(Short_t align) override; - void SetTextAngle(Float_t tangle) override; - void SetTextColor(Color_t tcolor) override; - void SetTextFont(Font_t tfont) override; - void SetTextSize(Float_t tsize) override; - void SetTextSizePixels(Int_t npixels) override; - //Marker attributes - Color_t GetMarkerColor() const override; - Style_t GetMarkerStyle() const override; - Size_t GetMarkerSize() const override; + void OnPad(TVirtualPad *) override; - void SetMarkerColor(Color_t mcolor) override; - void SetMarkerStyle(Style_t mstyle) override; - void SetMarkerSize(Size_t msize) override; + // Overwrite only attributes setters + void SetAttFill(const TAttFill &att) override; + void SetAttLine(const TAttLine &att) override; + void SetAttMarker(const TAttMarker &att) override; + void SetAttText(const TAttText &att) override; //2. "Off-screen management" part. Int_t CreateDrawable(UInt_t w, UInt_t h) override; @@ -100,6 +71,8 @@ class TGLPadPainter : public TVirtualPadPainter { void CopyDrawable(Int_t device, Int_t px, Int_t py) override; void DestroyDrawable(Int_t device) override; void SelectDrawable(Int_t device) override; + void UpdateDrawable(Int_t mode) override; + void SetDrawMode(Int_t device, Int_t mode) override; void InitPainter() override; void InvalidateCS() override; @@ -138,6 +111,8 @@ class TGLPadPainter : public TVirtualPadPainter { Bool_t IsCocoa() const override; + Bool_t IsSupportAlpha() const override { return kTRUE; } + private: //Attention! GL_PROJECTION will become diff --git a/graf3d/gl/inc/TGLPadUtils.h b/graf3d/gl/inc/TGLPadUtils.h index 9815d7d29bfe7..c92ff40c1a420 100644 --- a/graf3d/gl/inc/TGLPadUtils.h +++ b/graf3d/gl/inc/TGLPadUtils.h @@ -20,7 +20,8 @@ #include "RtypesCore.h" class TGLPadPainter;//For friend declarations. - +class TAttFill; +class TAttLine; /* All code here and in corresponding *.cxx file is only @@ -66,7 +67,7 @@ class FillAttribSet { UInt_t fStipple; Float_t fAlpha; public: - FillAttribSet(const PolygonStippleSet & set, Bool_t ignoreStipple); + FillAttribSet(const PolygonStippleSet & set, Bool_t ignoreStipple, const TAttFill *att = nullptr); ~FillAttribSet(); }; @@ -87,7 +88,7 @@ class LineAttribSet { Bool_t fSetWidth; Float_t fAlpha; public: - LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, Bool_t setWidth); + LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, Bool_t setWidth, const TAttLine *att = nullptr); ~LineAttribSet(); }; @@ -109,12 +110,20 @@ class MarkerPainter { mutable std::vector fCircle; + Size_t fMarkerSize; + Width_t fMarkerWidth; + Bool_t fSetMarker = kFALSE; + enum { kSmallCirclePts = 80, kLargeCirclePts = 150 }; public: + void SetMarkerSizeWidth(Size_t size, Width_t width); + Size_t GetMarkerSize() const; + Width_t GetMarkerWidth() const; + //Each function draw n markers. void DrawDot(UInt_t n, const TPoint *xy)const; void DrawPlus(UInt_t n, const TPoint *xy)const; diff --git a/graf3d/gl/src/TGLFontManager.cxx b/graf3d/gl/src/TGLFontManager.cxx index 58ea1188d5936..0cf76e2d95579 100644 --- a/graf3d/gl/src/TGLFontManager.cxx +++ b/graf3d/gl/src/TGLFontManager.cxx @@ -194,69 +194,37 @@ void TGLFont::RenderHelper(const Char *txt, Double_t x, Double_t y, Double_t ang */ const Double_t dx = urx - llx, dy = ury - lly; Double_t xc = 0., yc = 0.; - const UInt_t align = gVirtualX->GetTextAlign(); - //Here's the nice X11 bullshido: you call gVirtualX->SetTextAlign(11), + // if align was not set before - use value from gVirtualX + const UInt_t align = fTextAlign ? fTextAlign : gVirtualX->GetTextAlign(); + + //Timur: Here's the nice X11 bullshido: you call gVirtualX->SetTextAlign(11), //later gVirtualX->GetTextAling() will give you 7. Brilliant! //But with Cocoa you'll have 11. As it should be, of course. + //Sergey: problem with gVirtualX solved, now all platforms works same way + + const UInt_t hAlign = UInt_t(align / 10); + const UInt_t vAlign = UInt_t(align % 10); + switch (hAlign) { + case 1: + xc = 0.5 * dx; + break; + case 2: + break; + case 3: + xc = -0.5 * dy; + break; + } - if (gVirtualX->InheritsFrom("TGCocoa")) { - const UInt_t hAlign = UInt_t(align / 10); - switch (hAlign) { - case 1: - xc = 0.5 * dx; - break; - case 2: - break; - case 3: - xc = -0.5 * dy; - break; - } - - const UInt_t vAlign = UInt_t(align % 10); - switch (vAlign) { - case 1: - yc = 0.5 * dy; - break; - case 2: - break; - case 3: - yc = -0.5 * dy; - break; - } - } else { - switch (align) { - case 7: - xc += 0.5 * dx; - yc += 0.5 * dy; - break; - case 8: - yc += 0.5 * dy; - break; - case 9: - xc -= 0.5 * dx; - yc += 0.5 * dy; - break; - case 4: - xc += 0.5 * dx; - break; - case 5: - break; - case 6: - xc = -0.5 * dx; - break; - case 1: - xc += 0.5 * dx; - yc -= 0.5 * dy; - break; - case 2: - yc -= 0.5 * dy; - break; - case 3: - xc -= 0.5 * dx; - yc -= 0.5 * dy; - break; - } + switch (vAlign) { + case 1: + yc = 0.5 * dy; + break; + case 2: + break; + case 3: + yc = -0.5 * dy; + break; } glTranslated(x, y, 0.); diff --git a/graf3d/gl/src/TGLPadPainter.cxx b/graf3d/gl/src/TGLPadPainter.cxx index 61d88d7a9e2cf..3c55cef6354e1 100644 --- a/graf3d/gl/src/TGLPadPainter.cxx +++ b/graf3d/gl/src/TGLPadPainter.cxx @@ -21,6 +21,7 @@ #include "TImage.h" #include "TROOT.h" #include "TPad.h" +#include "TCanvas.h" #include "TColorGradient.h" #include "TGLPadPainter.h" @@ -61,98 +62,10 @@ TGLPadPainter::TGLPadPainter() fLocked(kTRUE) { fVp[0] = fVp[1] = fVp[2] = fVp[3] = 0; + fWinContext = 0; } -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Color_t TGLPadPainter::GetLineColor() const -{ - return gVirtualX->GetLineColor(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Style_t TGLPadPainter::GetLineStyle() const -{ - return gVirtualX->GetLineStyle(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Width_t TGLPadPainter::GetLineWidth() const -{ - return gVirtualX->GetLineWidth(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -void TGLPadPainter::SetLineColor(Color_t lcolor) -{ - gVirtualX->SetLineColor(lcolor); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -void TGLPadPainter::SetLineStyle(Style_t lstyle) -{ - gVirtualX->SetLineStyle(lstyle); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -void TGLPadPainter::SetLineWidth(Width_t lwidth) -{ - gVirtualX->SetLineWidth(lwidth); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Color_t TGLPadPainter::GetFillColor() const -{ - return gVirtualX->GetFillColor(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Style_t TGLPadPainter::GetFillStyle() const -{ - return gVirtualX->GetFillStyle(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. -///IsTransparent is implemented as inline function in TAttFill. - -Bool_t TGLPadPainter::IsTransparent() const -{ - return gVirtualX->IsTransparent(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -void TGLPadPainter::SetFillColor(Color_t fcolor) -{ - gVirtualX->SetFillColor(fcolor); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -void TGLPadPainter::SetFillStyle(Style_t fstyle) -{ - gVirtualX->SetFillStyle(fstyle); -} - //////////////////////////////////////////////////////////////////////////////// ///Delegate to gVirtualX. @@ -164,151 +77,68 @@ void TGLPadPainter::SetOpacity(Int_t percent) //////////////////////////////////////////////////////////////////////////////// ///Delegate to gVirtualX. -Short_t TGLPadPainter::GetTextAlign() const -{ - return gVirtualX->GetTextAlign(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Float_t TGLPadPainter::GetTextAngle() const -{ - return gVirtualX->GetTextAngle(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Color_t TGLPadPainter::GetTextColor() const -{ - return gVirtualX->GetTextColor(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Font_t TGLPadPainter::GetTextFont() const -{ - return gVirtualX->GetTextFont(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -Float_t TGLPadPainter::GetTextSize() const -{ - return gVirtualX->GetTextSize(); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - Float_t TGLPadPainter::GetTextMagnitude() const { return gVirtualX->GetTextMagnitude(); } //////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. +/// Select pad where current painting will be performed -void TGLPadPainter::SetTextAlign(Short_t align) +void TGLPadPainter::OnPad(TVirtualPad *pad) { - gVirtualX->SetTextAlign(align); + // GL painter does not use proper id for sub-pads (see CreateDrawable) + // so one always use canvas ID to execute TVirtualX-specific commands + if (!fWinContext) + fWinContext = gVirtualX->GetWindowContext(pad->GetCanvasID()); } //////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. +/// Set fill attributes -void TGLPadPainter::SetTextAngle(Float_t tangle) +void TGLPadPainter::SetAttFill(const TAttFill &att) { - gVirtualX->SetTextAngle(tangle); -} - -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. + TPadPainterBase::SetAttFill(att); -void TGLPadPainter::SetTextColor(Color_t tcolor) -{ - gVirtualX->SetTextColor(tcolor); + // TODO: dismiss in the future, gVirtualX attributes not needed in GL + if (fWinContext && gVirtualX) + gVirtualX->SetAttFill(fWinContext, att); } //////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. +/// Set line attributes -void TGLPadPainter::SetTextFont(Font_t tfont) +void TGLPadPainter::SetAttLine(const TAttLine &att) { - gVirtualX->SetTextFont(tfont); -} + TPadPainterBase::SetAttLine(att); -//////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. - -void TGLPadPainter::SetTextSize(Float_t tsize) -{ - gVirtualX->SetTextSize(tsize); + // TODO: dismiss in the future, gVirtualX attributes not needed in GL + if (fWinContext && gVirtualX) + gVirtualX->SetAttLine(fWinContext, att); } //////////////////////////////////////////////////////////////////////////////// -///Delegate to gVirtualX. +/// Set marker attributes -void TGLPadPainter::SetTextSizePixels(Int_t npixels) +void TGLPadPainter::SetAttMarker(const TAttMarker &att) { - gVirtualX->SetTextSizePixels(npixels); -} - + TPadPainterBase::SetAttMarker(att); -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Color_t TGLPadPainter::GetMarkerColor() const -{ - return gVirtualX->GetMarkerColor(); + // TODO: dismiss in the future, gVirtualX attributes not needed in GL + if (fWinContext && gVirtualX) + gVirtualX->SetAttMarker(fWinContext, att); } - //////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. +/// Set text attributes -Style_t TGLPadPainter::GetMarkerStyle() const +void TGLPadPainter::SetAttText(const TAttText &att) { - return gVirtualX->GetMarkerStyle(); -} - + TPadPainterBase::SetAttText(att); -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -Size_t TGLPadPainter::GetMarkerSize() const -{ - return gVirtualX->GetMarkerSize(); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TGLPadPainter::SetMarkerColor(Color_t mcolor) -{ - gVirtualX->SetMarkerColor(mcolor); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TGLPadPainter::SetMarkerStyle(Style_t mstyle) -{ - gVirtualX->SetMarkerStyle(mstyle); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Delegate to gVirtualX. - -void TGLPadPainter::SetMarkerSize(Size_t msize) -{ - gVirtualX->SetMarkerSize(msize); + // TODO: dismiss in the future, gVirtualX attributes not needed in GL + if (fWinContext && gVirtualX) + gVirtualX->SetAttText(fWinContext, att); } /* @@ -363,6 +193,7 @@ void TGLPadPainter::DestroyDrawable(Int_t /* device */) { // gVirtualX->SelectWindow(device); // gVirtualX->ClosePixmap(); + fWinContext = 0; } //////////////////////////////////////////////////////////////////////////////// @@ -371,12 +202,18 @@ void TGLPadPainter::DestroyDrawable(Int_t /* device */) ///this pixmap. For OpenGL this means the change of ///coordinate system and viewport. -void TGLPadPainter::SelectDrawable(Int_t /*device*/) +void TGLPadPainter::SelectDrawable(Int_t /* device */) { + auto pad = dynamic_cast(gPad); + if (!fWinContext && pad) + fWinContext = gVirtualX->GetWindowContext(pad->GetCanvasID()); + if (fLocked) return; - if (TPad *pad = dynamic_cast(gPad)) { + if (pad) { + // GL painter does not use proper id for sub-pads (see CreateDrawable) + // so one always use canvas ID to execute TVirtualX-specific commands Int_t px = 0, py = 0; pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py); @@ -404,6 +241,28 @@ void TGLPadPainter::SelectDrawable(Int_t /*device*/) } } +//////////////////////////////////////////////////////////////////////////////// +/// Call low-level update of selected drawable, redirect to gVirtualX. + +void TGLPadPainter::UpdateDrawable(Int_t mode) +{ + if (fWinContext) + gVirtualX->UpdateWindowW(fWinContext, mode); +} + + +//////////////////////////////////////////////////////////////////////////////// +/// Set drawing mode for specified device + +void TGLPadPainter::SetDrawMode(Int_t device, Int_t mode) +{ + auto ctxt = fWinContext; + if (device) + ctxt = gVirtualX->GetWindowContext(device); + if (ctxt) + gVirtualX->SetDrawModeW(ctxt, (TVirtualX::EDrawMode) mode); +} + //////////////////////////////////////////////////////////////////////////////// ///Init gl-pad painter: ///1. 2D painter does not use depth test, should not modify @@ -495,23 +354,25 @@ void TGLPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) //from TView3D::ExecuteRotateView. This means in fact, //that TView3D wants to draw itself in a XOR mode, via //gVirtualX. - if (gVirtualX->GetDrawMode() == TVirtualX::kInvert) { - gVirtualX->DrawLine(gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1), + // TODO: only here set line attributes to virtual x + if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { + gVirtualX->DrawLineW(fWinContext, + gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1), gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2)); } return; } - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE); + const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); glBegin(GL_LINES); glVertex2d(x1, y1); glVertex2d(x2, y2); glEnd(); - if (gVirtualX->GetLineWidth() > lineWidthTS) { - Double_t pointSize = gVirtualX->GetLineWidth(); + if (GetAttLine().GetLineWidth() > lineWidthTS) { + Double_t pointSize = GetAttLine().GetLineWidth(); if (pointSize > fLimits.GetMaxPointSize()) pointSize = fLimits.GetMaxPointSize(); glPointSize((GLfloat)pointSize); @@ -533,9 +394,18 @@ void TGLPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) { - if (fLocked) return; + if (fLocked) { + // this code used when crosshair cursor is drawn + if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { + // TODO: only here set line attributes to virtual x + gVirtualX->DrawLineW(fWinContext, + gPad->UtoAbsPixel(u1), gPad->VtoAbsPixel(v1), + gPad->UtoAbsPixel(u2), gPad->VtoAbsPixel(v2)); + } + return; + } - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE); + const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); const Double_t xRange = gPad->GetX2() - gPad->GetX1(); const Double_t yRange = gPad->GetY2() - gPad->GetY1(); @@ -550,9 +420,23 @@ void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) { - if (fLocked) return; + if (fLocked) { + //GL pad painter can be called in non-standard situation: + //not from TPad::Paint, but + //from TView3D::ExecuteRotateView. This means in fact, + //that TView3D wants to draw itself in a XOR mode, via + //gVirtualX. + // TODO: only here set line attributes to virtual x + if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { + gVirtualX->DrawBoxW(fWinContext, + gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1), + gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2), + (TVirtualX::EBoxMode) mode); + } + return; + } - if (IsGradientFill(gVirtualX->GetFillColor())) { + if (IsGradientFill(GetAttFill().GetFillColor())) { Double_t xs[] = {x1, x2, x2, x1}; Double_t ys[] = {y1, y1, y2, y2}; DrawPolygonWithGradient(4, xs, ys); @@ -560,14 +444,14 @@ void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, } if (mode == kHollow) { - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, 0, fLimits.GetMaxLineWidth(), kTRUE); + const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, 0, fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRectd(x1, y1, x2, y2); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLineWidth(1.f); } else { - const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);//Set filling parameters. + const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &GetAttFill());//Set filling parameters. glRectd(x1, y1, x2, y2); } } @@ -589,15 +473,15 @@ void TGLPadPainter::DrawFillArea(Int_t n, const Double_t *x, const Double_t *y) return; } - if (IsGradientFill(gVirtualX->GetFillColor())) + if (IsGradientFill(GetAttFill().GetFillColor())) return DrawPolygonWithGradient(n, x, y); - if (!gVirtualX->GetFillStyle()) { + if (!GetAttFill().GetFillStyle()) { fIsHollowArea = kTRUE; return DrawPolyLine(n, x, y); } - const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE); + const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &GetAttFill()); DrawTesselation(n, x, y); } @@ -609,7 +493,7 @@ void TGLPadPainter::DrawFillArea(Int_t n, const Float_t *x, const Float_t *y) { if (fLocked) return; - if (!gVirtualX->GetFillStyle()) { + if (!GetAttFill().GetFillStyle()) { fIsHollowArea = kTRUE; return DrawPolyLine(n, x, y); } @@ -621,7 +505,7 @@ void TGLPadPainter::DrawFillArea(Int_t n, const Float_t *x, const Float_t *y) fVs[i * 3 + 1] = y[i]; } - const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE); + const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &GetAttFill()); GLUtesselator *t = (GLUtesselator *)fTess.GetTess(); gluBeginPolygon(t); @@ -641,7 +525,7 @@ void TGLPadPainter::DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) { if (fLocked) return; - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE); + const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); glBegin(GL_LINE_STRIP); @@ -654,8 +538,8 @@ void TGLPadPainter::DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) } glEnd(); - if (gVirtualX->GetLineWidth() > lineWidthTS) { - Double_t pointSize = gVirtualX->GetLineWidth(); + if (GetAttLine().GetLineWidth() > lineWidthTS) { + Double_t pointSize = GetAttLine().GetLineWidth(); if (pointSize > fLimits.GetMaxPointSize()) pointSize = fLimits.GetMaxPointSize(); glPointSize((GLfloat)pointSize); @@ -678,7 +562,7 @@ void TGLPadPainter::DrawPolyLine(Int_t n, const Float_t *x, const Float_t *y) { if (fLocked) return; - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE); + const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); glBegin(GL_LINE_STRIP); @@ -700,7 +584,7 @@ void TGLPadPainter::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t * { if (fLocked) return; - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE); + const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); const Double_t xRange = gPad->GetX2() - gPad->GetX1(); const Double_t yRange = gPad->GetY2() - gPad->GetY1(); const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1(); @@ -760,15 +644,18 @@ void TGLPadPainter::DrawPolyMarker() const TGLEnableGuard blendGuard(GL_BLEND); Float_t rgba[4] = {}; - Rgl::Pad::ExtractRGBA(gVirtualX->GetMarkerColor(), rgba); + Rgl::Pad::ExtractRGBA(GetAttMarker().GetMarkerColor(), rgba); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4fv(rgba); - const Width_t w = TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle()))); + + const Width_t w = TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(GetAttMarker().GetMarkerStyle()))); glLineWidth(w > fLimits.GetMaxLineWidth() ? fLimits.GetMaxLineWidth() : !w ? 1.f : w); + fMarker.SetMarkerSizeWidth(GetAttMarker().GetMarkerSize(), w); + const TPoint *xy = &fPoly[0]; - const Style_t markerStyle = TAttMarker::GetMarkerStyleBase(gVirtualX->GetMarkerStyle()); + const Style_t markerStyle = TAttMarker::GetMarkerStyleBase(GetAttMarker().GetMarkerStyle()); const UInt_t n = UInt_t(fPoly.size()); switch (markerStyle) { case kDot: @@ -904,7 +791,7 @@ void TGLPadPainter::DrawTextHelper(Double_t x, Double_t y, const Char *text, ETe glMatrixMode(GL_MODELVIEW); Float_t rgba[4] = {}; - Rgl::Pad::ExtractRGBA(gVirtualX->GetTextColor(), rgba); + Rgl::Pad::ExtractRGBA(GetAttText().GetTextColor(), rgba); glColor4fv(rgba); //10 is the first valid font index. @@ -912,13 +799,15 @@ void TGLPadPainter::DrawTextHelper(Double_t x, Double_t y, const Char *text, ETe //shift - is the shift to access "extended" fonts. const Int_t shift = TGLFontManager::GetExtendedFontStartIndex(); - Int_t fontIndex = TMath::Max(Short_t(10), gVirtualX->GetTextFont()); + Int_t fontIndex = TMath::Max(Short_t(10), GetAttText().GetTextFont()); if (fontIndex / 10 + shift > TGLFontManager::GetFontFileArray()->GetEntries()) fontIndex = 20 + shift * 10; else fontIndex += shift * 10; - fFM.RegisterFont(TMath::Max(Int_t(gVirtualX->GetTextSize()) - 1, 10),//kTexture does not work if size < 10. + fF.SetTextAlign(GetAttText().GetTextAlign()); + + fFM.RegisterFont(TMath::Max(Int_t(GetAttText().GetTextSize()) - 1, 10),//kTexture does not work if size < 10. TGLFontManager::GetFontNameFromId(fontIndex), TGLFont::kTexture, fF); fF.PreRender(); @@ -942,7 +831,7 @@ void TGLPadPainter::DrawText(Double_t x, Double_t y, const char *text, ETextMode { if (fLocked) return; - if (!gVirtualX->GetTextSize()) + if (!GetAttText().GetTextSize()) return; DrawTextHelper(x, y, text, mode); @@ -958,7 +847,7 @@ void TGLPadPainter::DrawText(Double_t x, Double_t y, const wchar_t *text, ETextM { if (fLocked) return; - if (!gVirtualX->GetTextSize()) + if (!GetAttText().GetTextSize()) return; DrawTextHelper(x, y, text, mode); @@ -1059,11 +948,11 @@ void TGLPadPainter::RestoreViewport() void TGLPadPainter::SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const { - TVirtualPad *canvas = (TVirtualPad *)pad->GetCanvas(); + auto canvas = pad->GetCanvas(); if (!canvas) return; - gROOT->ProcessLine(Form("((TCanvas *)0x%zx)->Flush();", (size_t)canvas)); + canvas->Flush(); std::vector buff(canvas->GetWw() * canvas->GetWh()); glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -1192,10 +1081,8 @@ void TGLPadPainter::DrawPolygonWithGradient(Int_t n, const Double_t *x, const Do assert(x != nullptr && "DrawPolygonWithGradient, parameter 'x' is null"); assert(y != nullptr && "DrawPolygonWithGradient, parameter 'y' is null"); - assert(dynamic_cast(gROOT->GetColor(gVirtualX->GetFillColor())) != nullptr && - "DrawPolygonWithGradient, the current fill color is not a gradient fill"); - const TColorGradient * const grad = - dynamic_cast(gROOT->GetColor(gVirtualX->GetFillColor())); + auto grad = dynamic_cast(gROOT->GetColor(GetAttFill().GetFillColor())); + assert(grad != nullptr && "DrawPolygonWithGradient, the current fill color is not a gradient fill"); if (fLocked) return; diff --git a/graf3d/gl/src/TGLPadUtils.cxx b/graf3d/gl/src/TGLPadUtils.cxx index 8f47e37a4243a..574fadca9950c 100644 --- a/graf3d/gl/src/TGLPadUtils.cxx +++ b/graf3d/gl/src/TGLPadUtils.cxx @@ -118,14 +118,17 @@ Class to manipulate fill parameters. //////////////////////////////////////////////////////////////////////////////// ///Polygon stipple, if required. -FillAttribSet::FillAttribSet(const PolygonStippleSet &set, Bool_t ignoreStipple) +FillAttribSet::FillAttribSet(const PolygonStippleSet &set, Bool_t ignoreStipple, const TAttFill *att) : fStipple(0), fAlpha(1.) { - const UInt_t style = gVirtualX->GetFillStyle() / 1000; + Style_t fillStyle = att ? att->GetFillStyle() : gVirtualX->GetFillStyle(); + Color_t fillColor = att ? att->GetFillColor() : gVirtualX->GetFillColor(); + + const UInt_t style = fillStyle / 1000; if (!ignoreStipple) { if (style == 3) { - const UInt_t fasi = gVirtualX->GetFillStyle() % 1000; + const UInt_t fasi = fillStyle % 1000; fStipple = (fasi >= 1 && fasi <=25) ? fasi : 2; glPolygonStipple(&set.fStipples[fStipple * PolygonStippleSet::kStippleSize]); glEnable(GL_POLYGON_STIPPLE); @@ -134,7 +137,7 @@ FillAttribSet::FillAttribSet(const PolygonStippleSet &set, Bool_t ignoreStipple) // Color and transparency Float_t rgba[] = {0.f, 0.f, 0.f, 1.f}; - ExtractRGBA(gVirtualX->GetFillColor(), rgba); + ExtractRGBA(fillColor, rgba); fAlpha = rgba[3]; if (fAlpha<1.) { glEnable(GL_BLEND); @@ -171,7 +174,7 @@ Set/unset line attributes. ///Set up line parameters. ///Smooth. -LineAttribSet::LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, Bool_t setWidth) +LineAttribSet::LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, Bool_t setWidth, const TAttLine *att) : fSmooth(smooth), fStipple(stipple), fSetWidth(setWidth), fAlpha(0.8) { if (fSmooth) { @@ -181,6 +184,9 @@ LineAttribSet::LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, B glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); } + Color_t lineColor = att ? att->GetLineColor() : gVirtualX->GetLineColor(); + Width_t lineWidth = att ? att->GetLineWidth() : gVirtualX->GetLineWidth(); + //Stipple. if (fStipple > 1) { if (fStipple >= gMaxStipple) @@ -193,7 +199,7 @@ LineAttribSet::LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, B //Color and transparency Float_t rgba[] = {0.f, 0.f, 0.f, 0.8f}; - ExtractRGBA(gVirtualX->GetLineColor(), rgba); + ExtractRGBA(lineColor, rgba); fAlpha = rgba[3]; if (fAlpha<0.8) { glEnable(GL_BLEND); @@ -203,8 +209,7 @@ LineAttribSet::LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, B //Width. if (fSetWidth) { - const Width_t w = gVirtualX->GetLineWidth(); - glLineWidth(w > maxWidth ? maxWidth : !w ? 1.f : w); + glLineWidth(lineWidth > maxWidth ? maxWidth : !lineWidth ? 1.f : lineWidth); } } @@ -228,6 +233,34 @@ LineAttribSet::~LineAttribSet() Auxiliary class to draw markers in a gl-pad. */ +//////////////////////////////////////////////////////////////////////////////// +/// Set marker size and line width + +void MarkerPainter::SetMarkerSizeWidth(Size_t size, Width_t width) +{ + fSetMarker = kTRUE; + fMarkerSize = size; + fMarkerWidth = width; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get marker size +/// If not set before - use gVirtualX value + +Size_t MarkerPainter::GetMarkerSize() const +{ + return fSetMarker ? fMarkerSize : gVirtualX->GetMarkerSize(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Get marker width +/// If not set before - use gVirtualX value + +Width_t MarkerPainter::GetMarkerWidth() const +{ + return fSetMarker ? fMarkerWidth : TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle()); +} + //////////////////////////////////////////////////////////////////////////////// /// Simple 1-pixel dots. @@ -246,7 +279,7 @@ void MarkerPainter::DrawDot(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawPlus(UInt_t n, const TPoint *xy)const { - const Double_t im = 4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5; + const Double_t im = 4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5; glBegin(GL_LINES); for (UInt_t i = 0; i < n; ++i) { @@ -266,7 +299,7 @@ void MarkerPainter::DrawPlus(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawStar(UInt_t n, const TPoint *xy)const { - SCoord_t im = SCoord_t(4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5); + SCoord_t im = SCoord_t(4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5); fStar[0].fX = -im; fStar[0].fY = 0; fStar[1].fX = im; fStar[1].fY = 0; fStar[2].fX = 0 ; fStar[2].fY = -im; @@ -300,7 +333,7 @@ void MarkerPainter::DrawStar(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawX(UInt_t n, const TPoint *xy)const { - const Double_t im = 0.707 * (4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5) + 0.5; + const Double_t im = 0.707 * (4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5) + 0.5; glBegin(GL_LINES); @@ -353,7 +386,7 @@ void CalculateCircle(std::vector &circle, Double_t r, UInt_t pts); void MarkerPainter::DrawCircle(UInt_t n, const TPoint *xy)const { - Double_t r = 4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5; + Double_t r = 4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5; if (r > 100.) r = 100.;//as in TGX11. @@ -378,7 +411,7 @@ void MarkerPainter::DrawFullDotLarge(UInt_t n, const TPoint *xy)const fCircle.clear(); fCircle.push_back(TPoint(0, 0)); - Double_t r = 4 * gVirtualX->GetMarkerSize() + 0.5; + Double_t r = 4 * GetMarkerSize() + 0.5; if (r > 100.) r = 100;//as in TGX11. @@ -399,7 +432,7 @@ void MarkerPainter::DrawFullDotLarge(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullSquare(UInt_t n, const TPoint *xy)const { - const Double_t im = 4 * gVirtualX->GetMarkerSize() + 0.5; + const Double_t im = 4 * GetMarkerSize() + 0.5; for (UInt_t i = 0; i < n; ++i) glRectd(xy[i].fX - im, xy[i].fY - im, xy[i].fX + im, xy[i].fY + im); } @@ -408,7 +441,7 @@ void MarkerPainter::DrawFullSquare(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullTrianlgeUp(UInt_t n, const TPoint *xy)const { - const Double_t im = 4 * gVirtualX->GetMarkerSize() + 0.5; + const Double_t im = 4 * GetMarkerSize() + 0.5; for (UInt_t i = 0; i < n; ++i) { const Double_t x = xy[i].fX; const Double_t y = xy[i].fY; @@ -424,7 +457,7 @@ void MarkerPainter::DrawFullTrianlgeUp(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullTrianlgeDown(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); for (UInt_t i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -441,7 +474,7 @@ void MarkerPainter::DrawFullTrianlgeDown(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawDiamond(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4.00 * MarkerSizeReduced + 0.5); const Int_t imx = Int_t(2.66 * MarkerSizeReduced + 0.5); @@ -462,8 +495,8 @@ void MarkerPainter::DrawDiamond(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullDiamond(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t imx = Int_t(2.66 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t imx = Int_t(2.66 * GetMarkerSize() + 0.5); for (UInt_t i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -482,7 +515,7 @@ void MarkerPainter::DrawFullDiamond(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenTrianlgeDown(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5); + const Int_t im = Int_t(4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5); for (UInt_t i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -499,7 +532,7 @@ void MarkerPainter::DrawOpenTrianlgeDown(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenCross(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4.00 * MarkerSizeReduced + 0.5); const Int_t imx = Int_t(1.33 * MarkerSizeReduced + 0.5); @@ -528,8 +561,8 @@ void MarkerPainter::DrawOpenCross(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullCross(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t imx = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t imx = Int_t(1.33 * GetMarkerSize() + 0.5); for (UInt_t i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -561,11 +594,11 @@ void MarkerPainter::DrawFullCross(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullStar(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im1 = Int_t(0.66 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im3 = Int_t(2.66 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im4 = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im1 = Int_t(0.66 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(2.00 * GetMarkerSize() + 0.5); + const Int_t im3 = Int_t(2.66 * GetMarkerSize() + 0.5); + const Int_t im4 = Int_t(1.33 * GetMarkerSize() + 0.5); for (UInt_t i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -614,7 +647,7 @@ void MarkerPainter::DrawFullStar(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenStar(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4.00 * MarkerSizeReduced + 0.5); const Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5); const Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5); @@ -644,7 +677,7 @@ void MarkerPainter::DrawOpenStar(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenSquareDiagonal(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5); + const Int_t im = Int_t(4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -667,7 +700,7 @@ void MarkerPainter::DrawOpenSquareDiagonal(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenDiamondCross(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4. * (gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.) + 0.5); + const Int_t im = Int_t(4. * (GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.) + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -690,7 +723,7 @@ void MarkerPainter::DrawOpenDiamondCross(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenThreeTriangles(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4. * MarkerSizeReduced + 0.5); const Int_t im2 = Int_t(2. * MarkerSizeReduced + 0.5); @@ -717,7 +750,7 @@ void MarkerPainter::DrawOpenThreeTriangles(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOctagonCross(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4. * MarkerSizeReduced + 0.5); const Int_t im2 = Int_t(2. * MarkerSizeReduced + 0.5); @@ -749,8 +782,8 @@ void MarkerPainter::DrawOctagonCross(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullThreeTriangles(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(2.00 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -775,7 +808,7 @@ void MarkerPainter::DrawFullThreeTriangles(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenFourTrianglesX(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4. * MarkerSizeReduced + 0.5); const Int_t im2 = Int_t(2. * MarkerSizeReduced + 0.5); @@ -805,8 +838,8 @@ void MarkerPainter::DrawOpenFourTrianglesX(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullFourTrianglesX(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(2.00 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -834,7 +867,7 @@ void MarkerPainter::DrawFullFourTrianglesX(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenDoubleDiamond(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4.00 * MarkerSizeReduced + 0.5); const Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5); @@ -860,8 +893,8 @@ void MarkerPainter::DrawOpenDoubleDiamond(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullDoubleDiamond(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im4 = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im4 = Int_t(1.33 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -914,7 +947,7 @@ void MarkerPainter::DrawFullDoubleDiamond(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenFourTrianglesPlus(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4. * MarkerSizeReduced + 0.5); const Int_t im2 = Int_t(2. * MarkerSizeReduced + 0.5); @@ -942,8 +975,8 @@ void MarkerPainter::DrawOpenFourTrianglesPlus(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullFourTrianglesPlus(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(2.00 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -969,7 +1002,7 @@ void MarkerPainter::DrawFullFourTrianglesPlus(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawOpenCrossX(UInt_t n, const TPoint *xy)const { - const Double_t MarkerSizeReduced = gVirtualX->GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(gVirtualX->GetMarkerStyle())/2.)/4.; + const Double_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(GetMarkerWidth()/2.)/4.; const Int_t im = Int_t(4. * MarkerSizeReduced + 0.5); const Int_t im2 = Int_t(2. * MarkerSizeReduced + 0.5); @@ -999,8 +1032,8 @@ void MarkerPainter::DrawOpenCrossX(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFullCrossX(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(2.00 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -1040,8 +1073,8 @@ void MarkerPainter::DrawFullCrossX(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFourSquaresX(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(2.00 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; @@ -1078,8 +1111,8 @@ void MarkerPainter::DrawFourSquaresX(UInt_t n, const TPoint *xy)const void MarkerPainter::DrawFourSquaresPlus(UInt_t n, const TPoint *xy)const { - const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5); - const Int_t im2 = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5); + const Int_t im = Int_t(4 * GetMarkerSize() + 0.5); + const Int_t im2 = Int_t(1.33 * GetMarkerSize() + 0.5); for (unsigned i = 0; i < n; ++i) { const Double_t x = xy[i].fX; diff --git a/graf3d/gl/src/TGLWSIncludes.h b/graf3d/gl/src/TGLWSIncludes.h index 6ea691ba915c5..d8261874e3d38 100644 --- a/graf3d/gl/src/TGLWSIncludes.h +++ b/graf3d/gl/src/TGLWSIncludes.h @@ -20,9 +20,6 @@ #if defined(WIN32) #include #else -#if defined(__APPLE__) && !defined(R__HAS_COCOA) -#define GLEW_APPLE_GLX -#endif #if !defined(R__HAS_COCOA) #include #endif diff --git a/graf3d/gl/src/gl2ps.cxx b/graf3d/gl/src/gl2ps.cxx deleted file mode 100644 index de21e664871c7..0000000000000 --- a/graf3d/gl/src/gl2ps.cxx +++ /dev/null @@ -1,6034 +0,0 @@ -// @(#)root/gl:$Id$ -/* - * GL2PS, an OpenGL to PostScript Printing Library - * Copyright (C) 1999-2009 C. Geuzaine - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of either: - * - * a) the GNU Library General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your - * option) any later version; or - * - * b) the GL2PS License as published by Christophe Geuzaine, either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either - * the GNU Library General Public License or the GL2PS License for - * more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library in the file named "COPYING.LGPL"; - * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, - * Cambridge, MA 02139, USA. - * - * You should have received a copy of the GL2PS License with this - * library in the file named "COPYING.GL2PS"; if not, I will be glad - * to provide one. - * - * Contributors: - * Michael Sweet - * Marc Ume - * Jean-Francois Remacle - * Bart Kaptein - * Quy Nguyen-Dai - * Sam Buss - * Shane Hill - * Romain Boman - * Rouben Rostamian - * Diego Santa Cruz - * Shahzad Muzaffar - * Lassi Tuura - * Guy Barrand - * Prabhu Ramachandran - * Micha Bieber - * Olivier Couet - * Shai Ayal - * Fabian Wenzel - * Ian D. Gay - * Cosmin Truta - * Baiju Devani - * Alexander Danilov - * - * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/. - * Please report all bugs and problems to . - */ - -#include "gl2ps.h" - -#include -#include -#include -#include -#include -#include -#include - -#if defined(GL2PS_HAVE_ZLIB) -#include -#endif - -#if defined(GL2PS_HAVE_LIBPNG) -#include -#endif - -/********************************************************************* - * - * Private definitions, data structures and prototypes - * - *********************************************************************/ - -/* Magic numbers (assuming that the order of magnitude of window - coordinates is 10^3) */ - -#define GL2PS_EPSILON 5.0e-3F -#define GL2PS_ZSCALE 1000.0F -#define GL2PS_ZOFFSET 5.0e-2F -#define GL2PS_ZOFFSET_LARGE 20.0F -#define GL2PS_ZERO(arg) (fabs(arg) < 1.e-20) - -/* Primitive types */ - -#define GL2PS_NO_TYPE -1 -#define GL2PS_TEXT 1 -#define GL2PS_POINT 2 -#define GL2PS_LINE 3 -#define GL2PS_QUADRANGLE 4 -#define GL2PS_TRIANGLE 5 -#define GL2PS_PIXMAP 6 -#define GL2PS_IMAGEMAP 7 -#define GL2PS_IMAGEMAP_WRITTEN 8 -#define GL2PS_IMAGEMAP_VISIBLE 9 -#define GL2PS_SPECIAL 10 - -/* BSP tree primitive comparison */ - -#define GL2PS_COINCIDENT 1 -#define GL2PS_IN_FRONT_OF 2 -#define GL2PS_IN_BACK_OF 3 -#define GL2PS_SPANNING 4 - -/* 2D BSP tree primitive comparison */ - -#define GL2PS_POINT_COINCIDENT 0 -#define GL2PS_POINT_INFRONT 1 -#define GL2PS_POINT_BACK 2 - -/* Internal feedback buffer pass-through tokens */ - -#define GL2PS_BEGIN_OFFSET_TOKEN 1 -#define GL2PS_END_OFFSET_TOKEN 2 -#define GL2PS_BEGIN_BOUNDARY_TOKEN 3 -#define GL2PS_END_BOUNDARY_TOKEN 4 -#define GL2PS_BEGIN_STIPPLE_TOKEN 5 -#define GL2PS_END_STIPPLE_TOKEN 6 -#define GL2PS_POINT_SIZE_TOKEN 7 -#define GL2PS_LINE_WIDTH_TOKEN 8 -#define GL2PS_BEGIN_BLEND_TOKEN 9 -#define GL2PS_END_BLEND_TOKEN 10 -#define GL2PS_SRC_BLEND_TOKEN 11 -#define GL2PS_DST_BLEND_TOKEN 12 -#define GL2PS_IMAGEMAP_TOKEN 13 -#define GL2PS_DRAW_PIXELS_TOKEN 14 -#define GL2PS_TEXT_TOKEN 15 - -typedef enum { - T_UNDEFINED = -1, - T_CONST_COLOR = 1, - T_VAR_COLOR = 1<<1, - T_ALPHA_1 = 1<<2, - T_ALPHA_LESS_1 = 1<<3, - T_VAR_ALPHA = 1<<4 -} GL2PS_TRIANGLE_PROPERTY; - -typedef GLfloat GL2PSxyz[3]; -typedef GLfloat GL2PSplane[4]; - -typedef struct _GL2PSbsptree2d GL2PSbsptree2d; - -struct _GL2PSbsptree2d { - GL2PSplane plane; - GL2PSbsptree2d *front, *back; -}; - -typedef struct { - GLint nmax, size, incr, n; - char *array; -} GL2PSlist; - -typedef struct _GL2PSbsptree GL2PSbsptree; - -struct _GL2PSbsptree { - GL2PSplane plane; - GL2PSlist *primitives; - GL2PSbsptree *front, *back; -}; - -typedef struct { - GL2PSxyz xyz; - GL2PSrgba rgba; -} GL2PSvertex; - -typedef struct { - GL2PSvertex vertex[3]; - int prop; -} GL2PStriangle; - -typedef struct { - GLshort fontsize; - char *str, *fontname; - /* Note: for a 'special' string, 'alignment' holds the format - (PostScript, PDF, etc.) of the special string */ - GLint alignment; - GLfloat angle; -} GL2PSstring; - -typedef struct { - GLsizei width, height; - /* Note: for an imagemap, 'type' indicates if it has already been - written to the file or not, and 'format' indicates if it is - visible or not */ - GLenum format, type; - GLfloat *pixels; -} GL2PSimage; - -typedef struct _GL2PSimagemap GL2PSimagemap; - -struct _GL2PSimagemap { - GL2PSimage *image; - GL2PSimagemap *next; -}; - -typedef struct { - GLshort type, numverts; - GLushort pattern; - char boundary, offset, culled; - GLint factor; - GLfloat width; - GL2PSvertex *verts; - union { - GL2PSstring *text; - GL2PSimage *image; - } data; -} GL2PSprimitive; - -typedef struct { -#if defined(GL2PS_HAVE_ZLIB) - Bytef *dest, *src, *start; - uLongf destLen, srcLen; -#else - int dummy; -#endif -} GL2PScompress; - -typedef struct{ - GL2PSlist* ptrlist; - int gsno, fontno, imno, shno, maskshno, trgroupno; - int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno; -} GL2PSpdfgroup; - -typedef struct { - /* General */ - GLint format, sort, options, colorsize, colormode, buffersize; - char *title, *producer, *filename; - GLboolean boundary, blending; - GLfloat *feedback, offset[2], lastlinewidth; - GLint viewport[4], blendfunc[2], lastfactor; - GL2PSrgba *colormap, lastrgba, threshold, bgcolor; - GLushort lastpattern; - GL2PSvertex lastvertex; - GL2PSlist *primitives, *auxprimitives; - FILE *stream; - GL2PScompress *compress; - GLboolean header; - - /* BSP-specific */ - GLint maxbestroot; - - /* Occlusion culling-specific */ - GLboolean zerosurfacearea; - GL2PSbsptree2d *imagetree; - GL2PSprimitive *primitivetoadd; - - /* PDF-specific */ - int streamlength; - GL2PSlist *pdfprimlist, *pdfgrouplist; - int *xreflist; - int objects_stack; /* available objects */ - int extgs_stack; /* graphics state object number */ - int font_stack; /* font object number */ - int im_stack; /* image object number */ - int trgroupobjects_stack; /* xobject numbers */ - int shader_stack; /* shader object numbers */ - int mshader_stack; /* mask shader object numbers */ - - /* for image map list */ - GL2PSimagemap *imagemap_head; - GL2PSimagemap *imagemap_tail; -} GL2PScontext; - -typedef struct { - void (*printHeader)(void); - void (*printFooter)(void); - void (*beginViewport)(GLint viewport[4]); - GLint (*endViewport)(void); - void (*printPrimitive)(void *data); - void (*printFinalPrimitive)(void); - const char *file_extension; - const char *description; -} GL2PSbackend; - -/* The gl2ps context. gl2ps is not thread safe (we should create a - local GL2PScontext during gl2psBeginPage) */ - -static GL2PScontext *gl2ps = NULL; - -/* Need to forward-declare this one */ - -static GLint gl2psPrintPrimitives(void); - -/********************************************************************* - * - * Utility routines - * - *********************************************************************/ - -static void gl2psMsg(GLint level, const char *fmt, ...) -{ - va_list args; - - if(!(gl2ps->options & GL2PS_SILENT)){ - switch(level){ - case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break; - case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break; - case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break; - } - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, "\n"); - } - /* if(level == GL2PS_ERROR) exit(1); */ -} - -static void *gl2psMalloc(size_t size) -{ - void *ptr; - - if(!size) return(NULL); - ptr = malloc(size); - if(!ptr){ - gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory"); - exit(1); - } - return(ptr); -} - -static void *gl2psRealloc(void *ptr, size_t size) -{ - if(!size) return(NULL); - ptr = realloc(ptr, size); - if(!ptr){ - gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory"); - exit(1); - } - return(ptr); -} - -static void gl2psFree(void *ptr) -{ - if(!ptr) return; - free(ptr); -} - -static size_t gl2psWriteBigEndian(unsigned long data, size_t bytes) -{ - size_t i; - size_t size = sizeof(unsigned long); - for(i = 1; i <= bytes; ++i){ - fputc(0xff & (data >> (size-i) * 8), gl2ps->stream); - } - return bytes; -} - -/* zlib compression helper routines */ - -#if defined(GL2PS_HAVE_ZLIB) - -static void gl2psSetupCompress(void) -{ - gl2ps->compress = (GL2PScompress*)gl2psMalloc(sizeof(GL2PScompress)); - gl2ps->compress->src = NULL; - gl2ps->compress->start = NULL; - gl2ps->compress->dest = NULL; - gl2ps->compress->srcLen = 0; - gl2ps->compress->destLen = 0; -} - -static void gl2psFreeCompress(void) -{ - if(!gl2ps->compress) - return; - gl2psFree(gl2ps->compress->start); - gl2psFree(gl2ps->compress->dest); - gl2ps->compress->src = NULL; - gl2ps->compress->start = NULL; - gl2ps->compress->dest = NULL; - gl2ps->compress->srcLen = 0; - gl2ps->compress->destLen = 0; -} - -static int gl2psAllocCompress(unsigned int srcsize) -{ - gl2psFreeCompress(); - - if(!gl2ps->compress || !srcsize) - return GL2PS_ERROR; - - gl2ps->compress->srcLen = srcsize; - gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12); - gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen); - gl2ps->compress->start = gl2ps->compress->src; - gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen); - - return GL2PS_SUCCESS; -} - -static void *gl2psReallocCompress(unsigned int srcsize) -{ - if(!gl2ps->compress || !srcsize) - return NULL; - - if(srcsize < gl2ps->compress->srcLen) - return gl2ps->compress->start; - - gl2ps->compress->srcLen = srcsize; - gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12); - gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src, - gl2ps->compress->srcLen); - gl2ps->compress->start = gl2ps->compress->src; - gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest, - gl2ps->compress->destLen); - - return gl2ps->compress->start; -} - -static size_t gl2psWriteBigEndianCompress(unsigned long data, size_t bytes) -{ - size_t i; - size_t size = sizeof(unsigned long); - for(i = 1; i <= bytes; ++i){ - *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8)); - ++gl2ps->compress->src; - } - return bytes; -} - -static int gl2psDeflate(void) -{ - /* For compatibility with older zlib versions, we use compress(...) - instead of compress2(..., Z_BEST_COMPRESSION) */ - return compress(gl2ps->compress->dest, &gl2ps->compress->destLen, - gl2ps->compress->start, gl2ps->compress->srcLen); -} - -#endif - -static int gl2psPrintf(const char* fmt, ...) -{ - int ret; - va_list args; - -#if defined(GL2PS_HAVE_ZLIB) - unsigned int oldsize = 0; - static char buf[1000]; - if(gl2ps->options & GL2PS_COMPRESS){ - va_start(args, fmt); - ret = vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - oldsize = gl2ps->compress->srcLen; - gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + ret); - memcpy(gl2ps->compress->start+oldsize, buf, ret); - ret = 0; - } - else{ -#endif - va_start(args, fmt); - ret = vfprintf(gl2ps->stream, fmt, args); - va_end(args); -#if defined(GL2PS_HAVE_ZLIB) - } -#endif - return ret; -} - -static void gl2psPrintGzipHeader() -{ -#if defined(GL2PS_HAVE_ZLIB) - char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */ - 8, /* compression method: Z_DEFLATED */ - 0, /* flags */ - 0, 0, 0, 0, /* time */ - 2, /* extra flags: max compression */ - '\x03'}; /* OS code: 0x03 (Unix) */ - - if(gl2ps->options & GL2PS_COMPRESS){ - gl2psSetupCompress(); - /* add the gzip file header */ - fwrite(tmp, 10, 1, gl2ps->stream); - } -#endif -} - -static void gl2psPrintGzipFooter() -{ -#if defined(GL2PS_HAVE_ZLIB) - int n; - uLong crc, len; - char tmp[8]; - - if(gl2ps->options & GL2PS_COMPRESS){ - if(Z_OK != gl2psDeflate()){ - gl2psMsg(GL2PS_ERROR, "Zlib deflate error"); - } - else{ - /* determine the length of the header in the zlib stream */ - n = 2; /* CMF+FLG */ - if(gl2ps->compress->dest[1] & (1<<5)){ - n += 4; /* DICTID */ - } - /* write the data, without the zlib header and footer */ - fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4), - 1, gl2ps->stream); - /* add the gzip file footer */ - crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen); - for(n = 0; n < 4; ++n){ - tmp[n] = (char)(crc & 0xff); - crc >>= 8; - } - len = gl2ps->compress->srcLen; - for(n = 4; n < 8; ++n){ - tmp[n] = (char)(len & 0xff); - len >>= 8; - } - fwrite(tmp, 8, 1, gl2ps->stream); - } - gl2psFreeCompress(); - gl2psFree(gl2ps->compress); - gl2ps->compress = NULL; - } -#endif -} - -/* The list handling routines */ - -static void gl2psListRealloc(GL2PSlist *list, GLint n) -{ - if(!list){ - gl2psMsg(GL2PS_ERROR, "Cannot reallocate NULL list"); - return; - } - if(n <= 0) return; - if(!list->array){ - list->nmax = n; - list->array = (char*)gl2psMalloc(list->nmax * list->size); - } - else{ - if(n > list->nmax){ - list->nmax = ((n - 1) / list->incr + 1) * list->incr; - list->array = (char*)gl2psRealloc(list->array, - list->nmax * list->size); - } - } -} - -static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size) -{ - GL2PSlist *list; - - if(n < 0) n = 0; - if(incr <= 0) incr = 1; - list = (GL2PSlist*)gl2psMalloc(sizeof(GL2PSlist)); - list->nmax = 0; - list->incr = incr; - list->size = size; - list->n = 0; - list->array = NULL; - gl2psListRealloc(list, n); - return(list); -} - -static void gl2psListReset(GL2PSlist *list) -{ - if(!list) return; - list->n = 0; -} - -static void gl2psListDelete(GL2PSlist *list) -{ - if(!list) return; - gl2psFree(list->array); - gl2psFree(list); -} - -static void gl2psListAdd(GL2PSlist *list, void *data) -{ - if(!list){ - gl2psMsg(GL2PS_ERROR, "Cannot add into unallocated list"); - return; - } - list->n++; - gl2psListRealloc(list, list->n); - memcpy(&list->array[(list->n - 1) * list->size], data, list->size); -} - -static int gl2psListNbr(GL2PSlist *list) -{ - if(!list) - return 0; - return(list->n); -} - -static void *gl2psListPointer(GL2PSlist *list, GLint index) -{ - if(!list){ - gl2psMsg(GL2PS_ERROR, "Cannot point into unallocated list"); - return NULL; - } - if((index < 0) || (index >= list->n)){ - gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer"); - return NULL; - } - return(&list->array[index * list->size]); -} - -static void gl2psListSort(GL2PSlist *list, - int (*fcmp)(const void *a, const void *b)) -{ - if(!list) - return; - qsort(list->array, list->n, list->size, fcmp); -} - -static void gl2psListAction(GL2PSlist *list, void (*action)(void *data)) -{ - GLint i; - - for(i = 0; i < gl2psListNbr(list); i++){ - (*action)(gl2psListPointer(list, i)); - } -} - -static void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data)) -{ - GLint i; - - for(i = gl2psListNbr(list); i > 0; i--){ - (*action)(gl2psListPointer(list, i-1)); - } -} - -#if defined(GL2PS_HAVE_LIBPNG) - -static void gl2psListRead(GL2PSlist *list, int index, void *data) -{ - if((index < 0) || (index >= list->n)) - gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead"); - memcpy(data, &list->array[index * list->size], list->size); -} - -static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len) -{ - static const char cb64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - out[0] = cb64[ in[0] >> 2 ]; - out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; - out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='; - out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] : '='; -} - -static void gl2psListEncodeBase64(GL2PSlist *list) -{ - unsigned char *buffer, in[3], out[4]; - int i, n, index, len; - - n = list->n * list->size; - buffer = (unsigned char*)gl2psMalloc(n * sizeof(unsigned char)); - memcpy(buffer, list->array, n * sizeof(unsigned char)); - gl2psListReset(list); - - index = 0; - while(index < n) { - len = 0; - for(i = 0; i < 3; i++) { - if(index < n){ - in[i] = buffer[index]; - len++; - } - else{ - in[i] = 0; - } - index++; - } - if(len) { - gl2psEncodeBase64Block(in, out, len); - for(i = 0; i < 4; i++) - gl2psListAdd(list, &out[i]); - } - } - gl2psFree(buffer); -} - -#endif - -/* Helpers for rgba colors */ - -static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2) -{ - if(!GL2PS_ZERO(rgba1[0] - rgba2[0]) || - !GL2PS_ZERO(rgba1[1] - rgba2[1]) || - !GL2PS_ZERO(rgba1[2] - rgba2[2])) - return GL_FALSE; - return GL_TRUE; -} - -static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim) -{ - int i; - - for(i = 1; i < prim->numverts; i++){ - if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){ - return GL_FALSE; - } - } - return GL_TRUE; -} - -static GLboolean gl2psSameColorThreshold(int n, GL2PSrgba rgba[], - GL2PSrgba threshold) -{ - int i; - - if(n < 2) return GL_TRUE; - - for(i = 1; i < n; i++){ - if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] || - fabs(rgba[0][1] - rgba[i][1]) > threshold[1] || - fabs(rgba[0][2] - rgba[i][2]) > threshold[2]) - return GL_FALSE; - } - - return GL_TRUE; -} - -static void gl2psSetLastColor(GL2PSrgba rgba) -{ - int i; - for(i = 0; i < 3; ++i){ - gl2ps->lastrgba[i] = rgba[i]; - } -} - -static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y, - GLfloat *red, GLfloat *green, GLfloat *blue) -{ - - GLsizei width = im->width; - GLsizei height = im->height; - GLfloat *pixels = im->pixels; - GLfloat *pimag; - - /* OpenGL image is from down to up, PS image is up to down */ - switch(im->format){ - case GL_RGBA: - pimag = pixels + 4 * (width * (height - 1 - y) + x); - break; - case GL_RGB: - default: - pimag = pixels + 3 * (width * (height - 1 - y) + x); - break; - } - *red = *pimag; pimag++; - *green = *pimag; pimag++; - *blue = *pimag; pimag++; - - return (im->format == GL_RGBA) ? *pimag : 1.0F; -} - -/* Helper routines for pixmaps */ - -static GL2PSimage *gl2psCopyPixmap(GL2PSimage *im) -{ - int size; - GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); - - image->width = im->width; - image->height = im->height; - image->format = im->format; - image->type = im->type; - - switch(image->format){ - case GL_RGBA: - size = image->height * image->width * 4 * sizeof(GLfloat); - break; - case GL_RGB: - default: - size = image->height * image->width * 3 * sizeof(GLfloat); - break; - } - - image->pixels = (GLfloat*)gl2psMalloc(size); - memcpy(image->pixels, im->pixels, size); - - return image; -} - -static void gl2psFreePixmap(GL2PSimage *im) -{ - if(!im) - return; - gl2psFree(im->pixels); - gl2psFree(im); -} - -#if defined(GL2PS_HAVE_LIBPNG) - -#if !defined(png_jmpbuf) -# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#endif - -static void gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length) -{ - unsigned int i; - GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr); - for(i = 0; i < length; i++) - gl2psListAdd(png, &data[i]); -} - -static void gl2psUserFlushPNG(png_structp png_ptr) -{ -} - -static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png) -{ - png_structp png_ptr; - png_infop info_ptr; - unsigned char *row_data; - GLfloat dr, dg, db; - int row, col; - - if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) - return; - - if(!(info_ptr = png_create_info_struct(png_ptr))){ - png_destroy_write_struct(&png_ptr, NULL); - return; - } - - if(setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, &info_ptr); - return; - } - - png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG); - png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); - png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8, - PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); - png_write_info(png_ptr, info_ptr); - - row_data = (unsigned char*)gl2psMalloc(3 * pixmap->width * sizeof(unsigned char)); - for(row = 0; row < pixmap->height; row++){ - for(col = 0; col < pixmap->width; col++){ - gl2psGetRGB(pixmap, col, row, &dr, &dg, &db); - row_data[3*col] = (unsigned char)(255. * dr); - row_data[3*col+1] = (unsigned char)(255. * dg); - row_data[3*col+2] = (unsigned char)(255. * db); - } - png_write_row(png_ptr, (png_bytep)row_data); - } - gl2psFree(row_data); - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); -} - -#endif - -/* Helper routines for text strings */ - -static GLint gl2psAddText(GLint type, const char *str, const char *fontname, - GLshort fontsize, GLint alignment, GLfloat angle) -{ - GLfloat pos[4]; - GL2PSprimitive *prim; - GLboolean valid; - - if(!gl2ps || !str || !fontname) return GL2PS_UNINITIALIZED; - - if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS; - - glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid); - if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */ - - glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); - - prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - prim->type = type; - prim->boundary = 0; - prim->numverts = 1; - prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex)); - prim->verts[0].xyz[0] = pos[0]; - prim->verts[0].xyz[1] = pos[1]; - prim->verts[0].xyz[2] = pos[2]; - prim->culled = 0; - prim->offset = 0; - prim->pattern = 0; - prim->factor = 0; - prim->width = 1; - glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); - prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); - prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char)); - strcpy(prim->data.text->str, str); - prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char)); - strcpy(prim->data.text->fontname, fontname); - prim->data.text->fontsize = fontsize; - prim->data.text->alignment = alignment; - prim->data.text->angle = angle; - - gl2psListAdd(gl2ps->auxprimitives, &prim); - glPassThrough(GL2PS_TEXT_TOKEN); - - return GL2PS_SUCCESS; -} - -static GL2PSstring *gl2psCopyText(GL2PSstring *t) -{ - GL2PSstring *text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); - text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char)); - strcpy(text->str, t->str); - text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char)); - strcpy(text->fontname, t->fontname); - text->fontsize = t->fontsize; - text->alignment = t->alignment; - text->angle = t->angle; - - return text; -} - -static void gl2psFreeText(GL2PSstring *text) -{ - if(!text) - return; - gl2psFree(text->str); - gl2psFree(text->fontname); - gl2psFree(text); -} - -/* Helpers for blending modes */ - -static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor) -{ - /* returns TRUE if gl2ps supports the argument combination: only two - blending modes have been implemented so far */ - - if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) || - (sfactor == GL_ONE && dfactor == GL_ZERO) ) - return GL_TRUE; - return GL_FALSE; -} - -static void gl2psAdaptVertexForBlending(GL2PSvertex *v) -{ - /* Transforms vertex depending on the actual blending function - - currently the vertex v is considered as source vertex and its - alpha value is changed to 1.0 if source blending GL_ONE is - active. This might be extended in the future */ - - if(!v || !gl2ps) - return; - - if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){ - v->rgba[3] = 1.0F; - return; - } - - switch(gl2ps->blendfunc[0]){ - case GL_ONE: - v->rgba[3] = 1.0F; - break; - default: - break; - } -} - -static void gl2psAssignTriangleProperties(GL2PStriangle *t) -{ - /* int i; */ - - t->prop = T_VAR_COLOR; - - /* Uncommenting the following lines activates an even more fine - grained distinction between triangle types - please don't delete, - a remarkable amount of PDF handling code inside this file depends - on it if activated */ - /* - t->prop = T_CONST_COLOR; - for(i = 0; i < 3; ++i){ - if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) || - !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){ - t->prop = T_VAR_COLOR; - break; - } - } - */ - - if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) || - !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){ - t->prop |= T_VAR_ALPHA; - } - else{ - if(t->vertex[0].rgba[3] < 1) - t->prop |= T_ALPHA_LESS_1; - else - t->prop |= T_ALPHA_1; - } -} - -static void gl2psFillTriangleFromPrimitive(GL2PStriangle *t, GL2PSprimitive *p, - GLboolean assignprops) -{ - t->vertex[0] = p->verts[0]; - t->vertex[1] = p->verts[1]; - t->vertex[2] = p->verts[2]; - if(GL_TRUE == assignprops) - gl2psAssignTriangleProperties(t); -} - -static void gl2psInitTriangle(GL2PStriangle *t) -{ - int i; - GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} }; - for(i = 0; i < 3; i++) - t->vertex[i] = vertex; - t->prop = T_UNDEFINED; -} - -/* Miscellaneous helper routines */ - -static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p) -{ - GL2PSprimitive *prim; - - if(!p){ - gl2psMsg(GL2PS_ERROR, "Trying to copy an empty primitive"); - return NULL; - } - - prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - - prim->type = p->type; - prim->numverts = p->numverts; - prim->boundary = p->boundary; - prim->offset = p->offset; - prim->pattern = p->pattern; - prim->factor = p->factor; - prim->culled = p->culled; - prim->width = p->width; - prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex)); - memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex)); - - switch(prim->type){ - case GL2PS_PIXMAP : - prim->data.image = gl2psCopyPixmap(p->data.image); - break; - case GL2PS_TEXT : - case GL2PS_SPECIAL : - prim->data.text = gl2psCopyText(p->data.text); - break; - default: - break; - } - - return prim; -} - -static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2) -{ - if(!GL2PS_ZERO(p1[0] - p2[0]) || - !GL2PS_ZERO(p1[1] - p2[1]) || - !GL2PS_ZERO(p1[2] - p2[2])) - return GL_FALSE; - return GL_TRUE; -} - -/********************************************************************* - * - * 3D sorting routines - * - *********************************************************************/ - -static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane) -{ - return(plane[0] * point[0] + - plane[1] * point[1] + - plane[2] * point[2] + - plane[3]); -} - -static GLfloat gl2psPsca(GLfloat *a, GLfloat *b) -{ - return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]); -} - -static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c) -{ - c[0] = a[1]*b[2] - a[2]*b[1]; - c[1] = a[2]*b[0] - a[0]*b[2]; - c[2] = a[0]*b[1] - a[1]*b[0]; -} - -static GLfloat gl2psNorm(GLfloat *a) -{ - return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); -} - -static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c) -{ - GLfloat norm; - - gl2psPvec(a, b, c); - if(!GL2PS_ZERO(norm = gl2psNorm(c))){ - c[0] = c[0] / norm; - c[1] = c[1] / norm; - c[2] = c[2] / norm; - } - else{ - /* The plane is still wrong despite our tests in gl2psGetPlane. - Let's return a dummy value for now (this is a hack: we should - do more intelligent tests in GetPlane) */ - c[0] = c[1] = 0.0F; - c[2] = 1.0F; - } -} - -static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane) -{ - GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F}; - - switch(prim->type){ - case GL2PS_TRIANGLE : - case GL2PS_QUADRANGLE : - v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; - v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; - v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; - w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0]; - w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1]; - w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2]; - if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) || - (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){ - plane[0] = plane[1] = 0.0F; - plane[2] = 1.0F; - plane[3] = -prim->verts[0].xyz[2]; - } - else{ - gl2psGetNormal(v, w, plane); - plane[3] = - - plane[0] * prim->verts[0].xyz[0] - - plane[1] * prim->verts[0].xyz[1] - - plane[2] * prim->verts[0].xyz[2]; - } - break; - case GL2PS_LINE : - v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; - v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; - v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; - if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){ - plane[0] = plane[1] = 0.0F; - plane[2] = 1.0F; - plane[3] = -prim->verts[0].xyz[2]; - } - else{ - if(GL2PS_ZERO(v[0])) w[0] = 1.0F; - else if(GL2PS_ZERO(v[1])) w[1] = 1.0F; - else w[2] = 1.0F; - gl2psGetNormal(v, w, plane); - plane[3] = - - plane[0] * prim->verts[0].xyz[0] - - plane[1] * prim->verts[0].xyz[1] - - plane[2] * prim->verts[0].xyz[2]; - } - break; - case GL2PS_POINT : - case GL2PS_PIXMAP : - case GL2PS_TEXT : - case GL2PS_SPECIAL : - case GL2PS_IMAGEMAP: - plane[0] = plane[1] = 0.0F; - plane[2] = 1.0F; - plane[3] = -prim->verts[0].xyz[2]; - break; - default : - gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree"); - plane[0] = plane[1] = plane[3] = 0.0F; - plane[2] = 1.0F; - break; - } -} - -static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane, - GL2PSvertex *c) -{ - GL2PSxyz v; - GLfloat sect, psca; - - v[0] = b->xyz[0] - a->xyz[0]; - v[1] = b->xyz[1] - a->xyz[1]; - v[2] = b->xyz[2] - a->xyz[2]; - - if(!GL2PS_ZERO(psca = gl2psPsca(plane, v))) - sect = -gl2psComparePointPlane(a->xyz, plane) / psca; - else - sect = 0.0F; - - c->xyz[0] = a->xyz[0] + v[0] * sect; - c->xyz[1] = a->xyz[1] + v[1] * sect; - c->xyz[2] = a->xyz[2] + v[2] * sect; - - c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0]; - c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1]; - c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2]; - c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3]; -} - -static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane, - GL2PSprimitive *child, GLshort numverts, - GLshort *index0, GLshort *index1) -{ - GLshort i; - - if(parent->type == GL2PS_IMAGEMAP){ - child->type = GL2PS_IMAGEMAP; - child->data.image = parent->data.image; - } - else{ - if(numverts > 4){ - gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts); - numverts = 4; - } - switch(numverts){ - case 1 : child->type = GL2PS_POINT; break; - case 2 : child->type = GL2PS_LINE; break; - case 3 : child->type = GL2PS_TRIANGLE; break; - case 4 : child->type = GL2PS_QUADRANGLE; break; - default: child->type = GL2PS_NO_TYPE; break; - } - } - - child->boundary = 0; /* FIXME: not done! */ - child->culled = parent->culled; - child->offset = parent->offset; - child->pattern = parent->pattern; - child->factor = parent->factor; - child->width = parent->width; - child->numverts = numverts; - child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); - - for(i = 0; i < numverts; i++){ - if(index1[i] < 0){ - child->verts[i] = parent->verts[index0[i]]; - } - else{ - gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]], - plane, &child->verts[i]); - } - } -} - -static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, - GLshort i, GLshort j) -{ - GLint k; - - for(k = 0; k < *nb; k++){ - if((index0[k] == i && index1[k] == j) || - (index1[k] == i && index0[k] == j)) return; - } - index0[*nb] = i; - index1[*nb] = j; - (*nb)++; -} - -static GLshort gl2psGetIndex(GLshort i, GLshort num) -{ - return (i < num - 1) ? i + 1 : 0; -} - -static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane) -{ - GLint type = GL2PS_COINCIDENT; - GLshort i, j; - GLfloat d[5]; - - for(i = 0; i < prim->numverts; i++){ - d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane); - } - - if(prim->numverts < 2){ - return 0; - } - else{ - for(i = 0; i < prim->numverts; i++){ - j = gl2psGetIndex(i, prim->numverts); - if(d[j] > GL2PS_EPSILON){ - if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF; - else if(type != GL2PS_IN_BACK_OF) return 1; - if(d[i] < -GL2PS_EPSILON) return 1; - } - else if(d[j] < -GL2PS_EPSILON){ - if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF; - else if(type != GL2PS_IN_FRONT_OF) return 1; - if(d[i] > GL2PS_EPSILON) return 1; - } - } - } - return 0; -} - -static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane, - GL2PSprimitive **front, GL2PSprimitive **back) -{ - GLshort i, j, in = 0, out = 0; - GLshort in0[5] = {0}, in1[5] = {0}, out0[5] = {0}, out1[5] = {0}; - GLint type; - GLfloat d[5]; - - type = GL2PS_COINCIDENT; - - for(i = 0; i < prim->numverts; i++){ - d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane); - } - - switch(prim->type){ - case GL2PS_POINT : - if(d[0] > GL2PS_EPSILON) type = GL2PS_IN_BACK_OF; - else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF; - else type = GL2PS_COINCIDENT; - break; - default : - for(i = 0; i < prim->numverts; i++){ - j = gl2psGetIndex(i, prim->numverts); - if(d[j] > GL2PS_EPSILON){ - if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF; - else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING; - if(d[i] < -GL2PS_EPSILON){ - gl2psAddIndex(in0, in1, &in, i, j); - gl2psAddIndex(out0, out1, &out, i, j); - type = GL2PS_SPANNING; - } - gl2psAddIndex(out0, out1, &out, j, -1); - } - else if(d[j] < -GL2PS_EPSILON){ - if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF; - else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING; - if(d[i] > GL2PS_EPSILON){ - gl2psAddIndex(in0, in1, &in, i, j); - gl2psAddIndex(out0, out1, &out, i, j); - type = GL2PS_SPANNING; - } - gl2psAddIndex(in0, in1, &in, j, -1); - } - else{ - gl2psAddIndex(in0, in1, &in, j, -1); - gl2psAddIndex(out0, out1, &out, j, -1); - } - } - break; - } - - if(type == GL2PS_SPANNING){ - *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1); - gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1); - } - - return type; -} - -static void gl2psDivideQuad(GL2PSprimitive *quad, - GL2PSprimitive **t1, GL2PSprimitive **t2) -{ - *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - (*t1)->type = (*t2)->type = GL2PS_TRIANGLE; - (*t1)->numverts = (*t2)->numverts = 3; - (*t1)->culled = (*t2)->culled = quad->culled; - (*t1)->offset = (*t2)->offset = quad->offset; - (*t1)->pattern = (*t2)->pattern = quad->pattern; - (*t1)->factor = (*t2)->factor = quad->factor; - (*t1)->width = (*t2)->width = quad->width; - (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex)); - (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex)); - (*t1)->verts[0] = quad->verts[0]; - (*t1)->verts[1] = quad->verts[1]; - (*t1)->verts[2] = quad->verts[2]; - (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0); - (*t2)->verts[0] = quad->verts[0]; - (*t2)->verts[1] = quad->verts[2]; - (*t2)->verts[2] = quad->verts[3]; - (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 8) ? 4 : 0); -} - -static int gl2psCompareDepth(const void *a, const void *b) -{ - GL2PSprimitive *q, *w; - GLfloat dq = 0.0F, dw = 0.0F, diff; - int i; - - q = *(GL2PSprimitive**)a; - w = *(GL2PSprimitive**)b; - - for(i = 0; i < q->numverts; i++){ - dq += q->verts[i].xyz[2]; - } - dq /= (GLfloat)q->numverts; - - for(i = 0; i < w->numverts; i++){ - dw += w->verts[i].xyz[2]; - } - dw /= (GLfloat)w->numverts; - - diff = dq - dw; - if(diff > 0.){ - return -1; - } - else if(diff < 0.){ - return 1; - } - else{ - return 0; - } -} - -static int gl2psTrianglesFirst(const void *a, const void *b) -{ - GL2PSprimitive *q, *w; - - q = *(GL2PSprimitive**)a; - w = *(GL2PSprimitive**)b; - return(q->type < w->type ? 1 : -1); -} - -static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root) -{ - GLint i, j, count, best = 1000000, index = 0; - GL2PSprimitive *prim1, *prim2; - GL2PSplane plane; - GLint maxp; - - if(!gl2psListNbr(primitives)){ - gl2psMsg(GL2PS_ERROR, "Cannot fint root in empty primitive list"); - return 0; - } - - *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0); - - if(gl2ps->options & GL2PS_BEST_ROOT){ - maxp = gl2psListNbr(primitives); - if(maxp > gl2ps->maxbestroot){ - maxp = gl2ps->maxbestroot; - } - for(i = 0; i < maxp; i++){ - prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i); - gl2psGetPlane(prim1, plane); - count = 0; - for(j = 0; j < gl2psListNbr(primitives); j++){ - if(j != i){ - prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j); - count += gl2psTestSplitPrimitive(prim2, plane); - } - if(count > best) break; - } - if(count < best){ - best = count; - index = i; - *root = prim1; - if(!count) return index; - } - } - /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */ - return index; - } - else{ - return 0; - } -} - -static void gl2psFreeImagemap(GL2PSimagemap *list){ - GL2PSimagemap *next; - while(list != NULL){ - next = list->next; - gl2psFree(list->image->pixels); - gl2psFree(list->image); - gl2psFree(list); - list = next; - } -} - -static void gl2psFreePrimitive(void *data) -{ - GL2PSprimitive *q; - - q = *(GL2PSprimitive**)data; - gl2psFree(q->verts); - if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){ - gl2psFreeText(q->data.text); - } - else if(q->type == GL2PS_PIXMAP){ - gl2psFreePixmap(q->data.image); - } - gl2psFree(q); -} - -static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list) -{ - GL2PSprimitive *t1, *t2; - - if(prim->type != GL2PS_QUADRANGLE){ - gl2psListAdd(list, &prim); - } - else{ - gl2psDivideQuad(prim, &t1, &t2); - gl2psListAdd(list, &t1); - gl2psListAdd(list, &t2); - gl2psFreePrimitive(&prim); - } - -} - -static void gl2psFreeBspTree(GL2PSbsptree **tree) -{ - if(*tree){ - if((*tree)->back) gl2psFreeBspTree(&(*tree)->back); - if((*tree)->primitives){ - gl2psListAction((*tree)->primitives, gl2psFreePrimitive); - gl2psListDelete((*tree)->primitives); - } - if((*tree)->front) gl2psFreeBspTree(&(*tree)->front); - gl2psFree(*tree); - *tree = NULL; - } -} - -static GLboolean gl2psGreater(GLfloat f1, GLfloat f2) -{ - if(f1 > f2) return GL_TRUE; - else return GL_FALSE; -} - -static GLboolean gl2psLess(GLfloat f1, GLfloat f2) -{ - if(f1 < f2) return GL_TRUE; - else return GL_FALSE; -} - -static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives) -{ - GL2PSprimitive *prim = nullptr, *frontprim = nullptr, *backprim = nullptr; - GL2PSlist *frontlist, *backlist; - GLint i, index; - - tree->front = nullptr; - tree->back = nullptr; - tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - index = gl2psFindRoot(primitives, &prim); - gl2psGetPlane(prim, tree->plane); - gl2psAddPrimitiveInList(prim, tree->primitives); - - frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - - for(i = 0; i < gl2psListNbr(primitives); i++){ - if(i != index){ - prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i); - switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){ - case GL2PS_COINCIDENT: - gl2psAddPrimitiveInList(prim, tree->primitives); - break; - case GL2PS_IN_BACK_OF: - gl2psAddPrimitiveInList(prim, backlist); - break; - case GL2PS_IN_FRONT_OF: - gl2psAddPrimitiveInList(prim, frontlist); - break; - case GL2PS_SPANNING: - gl2psAddPrimitiveInList(backprim, backlist); - gl2psAddPrimitiveInList(frontprim, frontlist); - gl2psFreePrimitive(&prim); - break; - } - } - } - - if(gl2psListNbr(tree->primitives)){ - gl2psListSort(tree->primitives, gl2psTrianglesFirst); - } - - if(gl2psListNbr(frontlist)){ - gl2psListSort(frontlist, gl2psTrianglesFirst); - tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); - gl2psBuildBspTree(tree->front, frontlist); - } - else{ - gl2psListDelete(frontlist); - } - - if(gl2psListNbr(backlist)){ - gl2psListSort(backlist, gl2psTrianglesFirst); - tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); - gl2psBuildBspTree(tree->back, backlist); - } - else{ - gl2psListDelete(backlist); - } - - gl2psListDelete(primitives); -} - -static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon, - GLboolean (*compare)(GLfloat f1, GLfloat f2), - void (*action)(void *data), int inverse) -{ - GLfloat result; - - if(!tree) return; - - result = gl2psComparePointPlane(eye, tree->plane); - - if(GL_TRUE == compare(result, epsilon)){ - gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse); - if(inverse){ - gl2psListActionInverse(tree->primitives, action); - } - else{ - gl2psListAction(tree->primitives, action); - } - gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse); - } - else if(GL_TRUE == compare(-epsilon, result)){ - gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse); - if(inverse){ - gl2psListActionInverse(tree->primitives, action); - } - else{ - gl2psListAction(tree->primitives, action); - } - gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse); - } - else{ - gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse); - gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse); - } -} - -static void gl2psRescaleAndOffset() -{ - GL2PSprimitive *prim; - GLfloat minZ, maxZ, rangeZ, scaleZ; - GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ; - int i, j; - - if(!gl2psListNbr(gl2ps->primitives)) - return; - - /* get z-buffer range */ - prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0); - minZ = maxZ = prim->verts[0].xyz[2]; - for(i = 1; i < prim->numverts; i++){ - if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2]; - if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2]; - } - for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){ - prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i); - for(j = 0; j < prim->numverts; j++){ - if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2]; - if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2]; - } - } - rangeZ = (maxZ - minZ); - - /* rescale z-buffer coordinate in [0,GL2PS_ZSCALE], to make it of - the same order of magnitude as the x and y coordinates */ - scaleZ = GL2PS_ZERO(rangeZ) ? GL2PS_ZSCALE : (GL2PS_ZSCALE / rangeZ); - /* avoid precision loss (we use floats!) */ - if(scaleZ > 100000.F) scaleZ = 100000.F; - - /* apply offsets */ - for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){ - prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i); - for(j = 0; j < prim->numverts; j++){ - prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ; - } - if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) && - (prim->type == GL2PS_LINE)){ - if(gl2ps->sort == GL2PS_SIMPLE_SORT){ - prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE; - prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE; - } - else{ - prim->verts[0].xyz[2] -= GL2PS_ZOFFSET; - prim->verts[1].xyz[2] -= GL2PS_ZOFFSET; - } - } - else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){ - factor = gl2ps->offset[0]; - units = gl2ps->offset[1]; - area = - (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * - (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - - (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * - (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]); - if(!GL2PS_ZERO(area)){ - dZdX = - ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) * - (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) - - (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) * - (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area; - dZdY = - ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * - (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) - - (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * - (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area; - maxdZ = (GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY); - } - else{ - maxdZ = 0.0F; - } - dZ = factor * maxdZ + units; - prim->verts[0].xyz[2] += dZ; - prim->verts[1].xyz[2] += dZ; - prim->verts[2].xyz[2] += dZ; - } - } -} - -/********************************************************************* - * - * 2D sorting routines (for occlusion culling) - * - *********************************************************************/ - -static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane) -{ - GLfloat n; - - plane[0] = b[1] - a[1]; - plane[1] = a[0] - b[0]; - n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]); - plane[2] = 0.0F; - if(!GL2PS_ZERO(n)){ - plane[0] /= n; - plane[1] /= n; - plane[3] = -plane[0]*a[0]-plane[1]*a[1]; - return 1; - } - else{ - plane[0] = -1.0F; - plane[1] = 0.0F; - plane[3] = a[0]; - return 0; - } -} - -static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree) -{ - if(*tree){ - if((*tree)->back) gl2psFreeBspImageTree(&(*tree)->back); - if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front); - gl2psFree(*tree); - *tree = NULL; - } -} - -static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane) -{ - GLfloat pt_dis; - - pt_dis = gl2psComparePointPlane(point, plane); - if(pt_dis > GL2PS_EPSILON) return GL2PS_POINT_INFRONT; - else if(pt_dis < -GL2PS_EPSILON) return GL2PS_POINT_BACK; - else return GL2PS_POINT_COINCIDENT; -} - -static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim, - GL2PSbsptree2d **tree) -{ - GLint ret = 0; - GLint i; - GLint offset = 0; - GL2PSbsptree2d *head = NULL, *cur = NULL; - - if((*tree == NULL) && (prim->numverts > 2)){ - /* don't cull if transparent - for(i = 0; i < prim->numverts - 1; i++) - if(prim->verts[i].rgba[3] < 1.0F) return; - */ - head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); - for(i = 0; i < prim->numverts-1; i++){ - if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz, - prim->verts[i+1].xyz, - head->plane)){ - if(prim->numverts-i > 3){ - offset++; - } - else{ - gl2psFree(head); - return; - } - } - else{ - break; - } - } - head->back = NULL; - head->front = NULL; - for(i = 2+offset; i < prim->numverts; i++){ - ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane); - if(ret != GL2PS_POINT_COINCIDENT) break; - } - switch(ret){ - case GL2PS_POINT_INFRONT : - cur = head; - for(i = 1+offset; i < prim->numverts-1; i++){ - if(cur->front == NULL){ - cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); - } - if(gl2psGetPlaneFromPoints(prim->verts[i].xyz, - prim->verts[i+1].xyz, - cur->front->plane)){ - cur = cur->front; - cur->front = NULL; - cur->back = NULL; - } - } - if(cur->front == NULL){ - cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); - } - if(gl2psGetPlaneFromPoints(prim->verts[i].xyz, - prim->verts[offset].xyz, - cur->front->plane)){ - cur->front->front = NULL; - cur->front->back = NULL; - } - else{ - gl2psFree(cur->front); - cur->front = NULL; - } - break; - case GL2PS_POINT_BACK : - for(i = 0; i < 4; i++){ - head->plane[i] = -head->plane[i]; - } - cur = head; - for(i = 1+offset; i < prim->numverts-1; i++){ - if(cur->front == NULL){ - cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); - } - if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz, - prim->verts[i].xyz, - cur->front->plane)){ - cur = cur->front; - cur->front = NULL; - cur->back = NULL; - } - } - if(cur->front == NULL){ - cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); - } - if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz, - prim->verts[i].xyz, - cur->front->plane)){ - cur->front->front = NULL; - cur->front->back = NULL; - } - else{ - gl2psFree(cur->front); - cur->front = NULL; - } - break; - default: - gl2psFree(head); - return; - } - (*tree) = head; - } -} - -static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane) -{ - GLint i; - GLint pos; - - pos = gl2psCheckPoint(prim->verts[0].xyz, plane); - for(i = 1; i < prim->numverts; i++){ - pos |= gl2psCheckPoint(prim->verts[i].xyz, plane); - if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK)) return GL2PS_SPANNING; - } - if(pos & GL2PS_POINT_INFRONT) return GL2PS_IN_FRONT_OF; - else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF; - else return GL2PS_COINCIDENT; -} - -static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, - GLshort numverts, - GL2PSvertex *vertx) -{ - GLint i; - GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - - if(parent->type == GL2PS_IMAGEMAP){ - child->type = GL2PS_IMAGEMAP; - child->data.image = parent->data.image; - } - else { - switch(numverts){ - case 1 : child->type = GL2PS_POINT; break; - case 2 : child->type = GL2PS_LINE; break; - case 3 : child->type = GL2PS_TRIANGLE; break; - case 4 : child->type = GL2PS_QUADRANGLE; break; - default: child->type = GL2PS_NO_TYPE; break; /* FIXME */ - } - } - child->boundary = 0; /* FIXME: not done! */ - child->culled = parent->culled; - child->offset = parent->offset; - child->pattern = parent->pattern; - child->factor = parent->factor; - child->width = parent->width; - child->numverts = numverts; - child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); - for(i = 0; i < numverts; i++){ - child->verts[i] = vertx[i]; - } - return child; -} - -static void gl2psSplitPrimitive2D(GL2PSprimitive *prim, - GL2PSplane plane, - GL2PSprimitive **front, - GL2PSprimitive **back) -{ - /* cur will hold the position of the current vertex - prev will hold the position of the previous vertex - prev0 will hold the position of the vertex number 0 - v1 and v2 represent the current and previous vertices, respectively - flag is set if the current vertex should be checked against the plane */ - GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1; - - /* list of vertices that will go in front and back primitive */ - GL2PSvertex *front_list = NULL, *back_list = NULL; - - /* number of vertices in front and back list */ - GLshort front_count = 0, back_count = 0; - - for(i = 0; i <= prim->numverts; i++){ - v1 = i; - if(v1 == prim->numverts){ - if(prim->numverts < 3) break; - v1 = 0; - v2 = prim->numverts - 1; - cur = prev0; - } - else if(flag){ - cur = gl2psCheckPoint(prim->verts[v1].xyz, plane); - if(i == 0){ - prev0 = cur; - } - } - if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) && - (i < prim->numverts)){ - if(cur == GL2PS_POINT_INFRONT){ - front_count++; - front_list = (GL2PSvertex*)gl2psRealloc(front_list, - sizeof(GL2PSvertex)*front_count); - front_list[front_count-1] = prim->verts[v1]; - } - else if(cur == GL2PS_POINT_BACK){ - back_count++; - back_list = (GL2PSvertex*)gl2psRealloc(back_list, - sizeof(GL2PSvertex)*back_count); - back_list[back_count-1] = prim->verts[v1]; - } - else{ - front_count++; - front_list = (GL2PSvertex*)gl2psRealloc(front_list, - sizeof(GL2PSvertex)*front_count); - front_list[front_count-1] = prim->verts[v1]; - back_count++; - back_list = (GL2PSvertex*)gl2psRealloc(back_list, - sizeof(GL2PSvertex)*back_count); - back_list[back_count-1] = prim->verts[v1]; - } - flag = 1; - } - else if((prev != cur) && (cur != 0) && (prev != 0)){ - if(v1 != 0){ - v2 = v1-1; - i--; - } - front_count++; - front_list = (GL2PSvertex*)gl2psRealloc(front_list, - sizeof(GL2PSvertex)*front_count); - gl2psCutEdge(&prim->verts[v2], &prim->verts[v1], - plane, &front_list[front_count-1]); - back_count++; - back_list = (GL2PSvertex*)gl2psRealloc(back_list, - sizeof(GL2PSvertex)*back_count); - back_list[back_count-1] = front_list[front_count-1]; - flag = 0; - } - prev = cur; - } - *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list); - *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list); - gl2psFree(front_list); - gl2psFree(back_list); -} - -static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree) -{ - GLint ret = 0; - GL2PSprimitive *frontprim = NULL, *backprim = NULL; - - /* FIXME: until we consider the actual extent of text strings and - pixmaps, never cull them. Otherwise the whole string/pixmap gets - culled as soon as the reference point is hidden */ - if(prim->type == GL2PS_PIXMAP || - prim->type == GL2PS_TEXT || - prim->type == GL2PS_SPECIAL){ - return 1; - } - - if(*tree == NULL){ - if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){ - gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree); - } - return 1; - } - else{ - switch(gl2psCheckPrimitive(prim, (*tree)->plane)){ - case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back); - case GL2PS_IN_FRONT_OF: - if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front); - else return 0; - case GL2PS_SPANNING: - gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim); - ret = gl2psAddInBspImageTree(backprim, &(*tree)->back); - if((*tree)->front != NULL){ - if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){ - ret = 1; - } - } - gl2psFree(frontprim->verts); - gl2psFree(frontprim); - gl2psFree(backprim->verts); - gl2psFree(backprim); - return ret; - case GL2PS_COINCIDENT: - if((*tree)->back != NULL){ - gl2ps->zerosurfacearea = GL_TRUE; - ret = gl2psAddInBspImageTree(prim, &(*tree)->back); - gl2ps->zerosurfacearea = GL_FALSE; - if(ret) return ret; - } - if((*tree)->front != NULL){ - gl2ps->zerosurfacearea = GL_TRUE; - ret = gl2psAddInBspImageTree(prim, &(*tree)->front); - gl2ps->zerosurfacearea = GL_FALSE; - if(ret) return ret; - } - if(prim->type == GL2PS_LINE) return 1; - else return 0; - } - } - return 0; -} - -static void gl2psAddInImageTree(void *data) -{ - GL2PSprimitive *prim = *(GL2PSprimitive **)data; - gl2ps->primitivetoadd = prim; - if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){ - prim->culled = 1; - } - else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){ - prim->culled = 1; - } - else if(prim->type == GL2PS_IMAGEMAP){ - prim->data.image->format = GL2PS_IMAGEMAP_VISIBLE; - } -} - -/* Boundary construction */ - -static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list) -{ - GL2PSprimitive *b; - GLshort i; - GL2PSxyz c; - - c[0] = c[1] = c[2] = 0.0F; - for(i = 0; i < prim->numverts; i++){ - c[0] += prim->verts[i].xyz[0]; - c[1] += prim->verts[i].xyz[1]; - } - c[0] /= prim->numverts; - c[1] /= prim->numverts; - - for(i = 0; i < prim->numverts; i++){ - if(prim->boundary & (GLint)pow(2., i)){ - b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - b->type = GL2PS_LINE; - b->offset = prim->offset; - b->pattern = prim->pattern; - b->factor = prim->factor; - b->culled = prim->culled; - b->width = prim->width; - b->boundary = 0; - b->numverts = 2; - b->verts = (GL2PSvertex*)gl2psMalloc(2 * sizeof(GL2PSvertex)); - -#if 0 /* FIXME: need to work on boundary offset... */ - v[0] = c[0] - prim->verts[i].xyz[0]; - v[1] = c[1] - prim->verts[i].xyz[1]; - v[2] = 0.0F; - norm = gl2psNorm(v); - v[0] /= norm; - v[1] /= norm; - b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0]; - b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1]; - b->verts[0].xyz[2] = prim->verts[i].xyz[2]; - v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0]; - v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1]; - norm = gl2psNorm(v); - v[0] /= norm; - v[1] /= norm; - b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0]; - b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1]; - b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2]; -#else - b->verts[0].xyz[0] = prim->verts[i].xyz[0]; - b->verts[0].xyz[1] = prim->verts[i].xyz[1]; - b->verts[0].xyz[2] = prim->verts[i].xyz[2]; - b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0]; - b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1]; - b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2]; -#endif - - b->verts[0].rgba[0] = 0.0F; - b->verts[0].rgba[1] = 0.0F; - b->verts[0].rgba[2] = 0.0F; - b->verts[0].rgba[3] = 0.0F; - b->verts[1].rgba[0] = 0.0F; - b->verts[1].rgba[1] = 0.0F; - b->verts[1].rgba[2] = 0.0F; - b->verts[1].rgba[3] = 0.0F; - gl2psListAdd(list, &b); - } - } - -} - -static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree) -{ - GLint i; - GL2PSprimitive *prim; - - if(!tree) return; - gl2psBuildPolygonBoundary(tree->back); - for(i = 0; i < gl2psListNbr(tree->primitives); i++){ - prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i); - if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives); - } - gl2psBuildPolygonBoundary(tree->front); -} - -/********************************************************************* - * - * Feedback buffer parser - * - *********************************************************************/ - -static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, - GL2PSvertex *verts, GLint offset, - GLushort pattern, GLint factor, - GLfloat width, char boundary) -{ - GL2PSprimitive *prim; - - prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - prim->type = type; - prim->numverts = numverts; - prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); - memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex)); - prim->boundary = boundary; - prim->offset = offset; - prim->pattern = pattern; - prim->factor = factor; - prim->width = width; - prim->culled = 0; - - /* FIXME: here we should have an option to split stretched - tris/quads to enhance SIMPLE_SORT */ - - gl2psListAdd(gl2ps->primitives, &prim); -} - -static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p) -{ - GLint i; - - v->xyz[0] = p[0]; - v->xyz[1] = p[1]; - v->xyz[2] = p[2]; - - if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){ - i = (GLint)(p[3] + 0.5); - v->rgba[0] = gl2ps->colormap[i][0]; - v->rgba[1] = gl2ps->colormap[i][1]; - v->rgba[2] = gl2ps->colormap[i][2]; - v->rgba[3] = gl2ps->colormap[i][3]; - return 4; - } - else{ - v->rgba[0] = p[3]; - v->rgba[1] = p[4]; - v->rgba[2] = p[5]; - v->rgba[3] = p[6]; - return 7; - } -} - -static void gl2psParseFeedbackBuffer(GLint used) -{ - char flag; - GLushort pattern = 0; - GLboolean boundary; - GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0; - GLfloat lwidth = 1.0F, psize = 1.0F; - GLfloat *current; - GL2PSvertex vertices[3]; - GL2PSprimitive *prim; - GL2PSimagemap *node; - - current = gl2ps->feedback; - boundary = gl2ps->boundary = GL_FALSE; - - while(used > 0){ - - if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE; - - switch((GLint)*current){ - case GL_POINT_TOKEN : - current ++; - used --; - i = gl2psGetVertex(&vertices[0], current); - current += i; - used -= i; - gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, - pattern, factor, psize, 0); - break; - case GL_LINE_TOKEN : - case GL_LINE_RESET_TOKEN : - current ++; - used --; - i = gl2psGetVertex(&vertices[0], current); - current += i; - used -= i; - i = gl2psGetVertex(&vertices[1], current); - current += i; - used -= i; - gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, - pattern, factor, lwidth, 0); - break; - case GL_POLYGON_TOKEN : - count = (GLint)current[1]; - current += 2; - used -= 2; - v = vtot = 0; - while(count > 0 && used > 0){ - i = gl2psGetVertex(&vertices[v], current); - gl2psAdaptVertexForBlending(&vertices[v]); - current += i; - used -= i; - count --; - vtot++; - if(v == 2){ - if(GL_TRUE == boundary){ - if(!count && vtot == 2) flag = 1|2|4; - else if(!count) flag = 2|4; - else if(vtot == 2) flag = 1|2; - else flag = 2; - } - else - flag = 0; - gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset, - pattern, factor, 1, flag); - vertices[1] = vertices[2]; - } - else - v ++; - } - break; - case GL_BITMAP_TOKEN : - case GL_DRAW_PIXEL_TOKEN : - case GL_COPY_PIXEL_TOKEN : - current ++; - used --; - i = gl2psGetVertex(&vertices[0], current); - current += i; - used -= i; - break; - case GL_PASS_THROUGH_TOKEN : - switch((GLint)current[1]){ - case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break; - case GL2PS_END_OFFSET_TOKEN : offset = 0; break; - case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE; break; - case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE; break; - case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break; - case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break; - case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break; - case GL2PS_BEGIN_STIPPLE_TOKEN : - current += 2; - used -= 2; - pattern = (GLushort)current[1]; - current += 2; - used -= 2; - factor = (GLint)current[1]; - break; - case GL2PS_SRC_BLEND_TOKEN : - current += 2; - used -= 2; - gl2ps->blendfunc[0] = (GLint)current[1]; - break; - case GL2PS_DST_BLEND_TOKEN : - current += 2; - used -= 2; - gl2ps->blendfunc[1] = (GLint)current[1]; - break; - case GL2PS_POINT_SIZE_TOKEN : - current += 2; - used -= 2; - psize = current[1]; - break; - case GL2PS_LINE_WIDTH_TOKEN : - current += 2; - used -= 2; - lwidth = current[1]; - break; - case GL2PS_IMAGEMAP_TOKEN : - prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive)); - prim->type = GL2PS_IMAGEMAP; - prim->boundary = 0; - prim->numverts = 4; - prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex)); - prim->culled = 0; - prim->offset = 0; - prim->pattern = 0; - prim->factor = 0; - prim->width = 1; - - node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap)); - node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); - node->image->type = 0; - node->image->format = 0; - node->next = NULL; - - if(gl2ps->imagemap_head == NULL) - gl2ps->imagemap_head = node; - else - gl2ps->imagemap_tail->next = node; - gl2ps->imagemap_tail = node; - prim->data.image = node->image; - - current += 2; used -= 2; - i = gl2psGetVertex(&prim->verts[0], ¤t[1]); - current += i; used -= i; - - node->image->width = (GLint)current[2]; - current += 2; used -= 2; - node->image->height = (GLint)current[2]; - prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5; - prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5; - for(i = 1; i < 4; i++){ - for(v = 0; v < 3; v++){ - prim->verts[i].xyz[v] = prim->verts[0].xyz[v]; - prim->verts[i].rgba[v] = prim->verts[0].rgba[v]; - } - prim->verts[i].rgba[v] = prim->verts[0].rgba[v]; - } - prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width; - prim->verts[2].xyz[0] = prim->verts[1].xyz[0]; - prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height; - prim->verts[3].xyz[1] = prim->verts[2].xyz[1]; - - sizeoffloat = sizeof(GLfloat); - v = 2 * sizeoffloat; - vtot = node->image->height + node->image->height * - ((node->image->width - 1) / 8); - node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot); - node->image->pixels[0] = prim->verts[0].xyz[0]; - node->image->pixels[1] = prim->verts[0].xyz[1]; - - for(i = 0; i < vtot; i += sizeoffloat){ - current += 2; used -= 2; - if((vtot - i) >= 4) - memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat); - else - memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i); - } - current++; used--; - gl2psListAdd(gl2ps->primitives, &prim); - break; - case GL2PS_DRAW_PIXELS_TOKEN : - case GL2PS_TEXT_TOKEN : - if(auxindex < gl2psListNbr(gl2ps->auxprimitives)) - gl2psListAdd(gl2ps->primitives, - gl2psListPointer(gl2ps->auxprimitives, auxindex++)); - else - gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer"); - break; - } - current += 2; - used -= 2; - break; - default : - gl2psMsg(GL2PS_WARNING, "Unknown token in buffer"); - current ++; - used --; - break; - } - } - - gl2psListReset(gl2ps->auxprimitives); -} - -/********************************************************************* - * - * PostScript routines - * - *********************************************************************/ - -static void gl2psWriteByte(unsigned char byte) -{ - unsigned char h = byte / 16; - unsigned char l = byte % 16; - gl2psPrintf("%x%x", h, l); -} - -static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im) -{ - GLuint nbhex, nbyte, nrgb, nbits; - GLuint row, col, ibyte, icase; - GLfloat dr, dg = 0.f, db = 0.f, fgrey; - unsigned char red = 0, green = 0, blue = 0, b, grey; - GLuint width = (GLuint)im->width; - GLuint height = (GLuint)im->height; - - /* FIXME: should we define an option for these? Or just keep the - 8-bit per component case? */ - int greyscale = 0; /* set to 1 to output greyscale image */ - int nbit = 8; /* number of bits per color compoment (2, 4 or 8) */ - - if((width <= 0) || (height <= 0)) return; - - gl2psPrintf("gsave\n"); - gl2psPrintf("%.2f %.2f translate\n", x, y); - gl2psPrintf("%d %d scale\n", width, height); - - if(greyscale){ /* greyscale */ - gl2psPrintf("/picstr %d string def\n", width); - gl2psPrintf("%d %d %d\n", width, height, 8); - gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); - gl2psPrintf("{ currentfile picstr readhexstring pop }\n"); - gl2psPrintf("image\n"); - for(row = 0; row < height; row++){ - for(col = 0; col < width; col++){ - gl2psGetRGB(im, col, row, &dr, &dg, &db); - fgrey = (0.30 * dr + 0.59 * dg + 0.11 * db); - grey = (unsigned char)(255. * fgrey); - gl2psWriteByte(grey); - } - gl2psPrintf("\n"); - } - nbhex = width * height * 2; - gl2psPrintf("%%%% nbhex digit :%d\n", nbhex); - } - else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */ - nrgb = width * 3; - nbits = nrgb * nbit; - nbyte = nbits / 8; - if((nbyte * 8) != nbits) nbyte++; - gl2psPrintf("/rgbstr %d string def\n", nbyte); - gl2psPrintf("%d %d %d\n", width, height, nbit); - gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); - gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n"); - gl2psPrintf("false 3\n"); - gl2psPrintf("colorimage\n"); - for(row = 0; row < height; row++){ - icase = 1; - col = 0; - b = 0; - for(ibyte = 0; ibyte < nbyte; ibyte++){ - if(icase == 1) { - if(col < width) { - gl2psGetRGB(im, col, row, &dr, &dg, &db); - } - else { - dr = dg = db = 0; - } - col++; - red = (unsigned char)(3. * dr); - green = (unsigned char)(3. * dg); - blue = (unsigned char)(3. * db); - b = red; - b = (b<<2) + green; - b = (b<<2) + blue; - if(col < width) { - gl2psGetRGB(im, col, row, &dr, &dg, &db); - } - else { - dr = dg = db = 0; - } - col++; - red = (unsigned char)(3. * dr); - green = (unsigned char)(3. * dg); - blue = (unsigned char)(3. * db); - b = (b<<2) + red; - gl2psWriteByte(b); - b = 0; - icase++; - } - else if(icase == 2) { - b = green; - b = (b<<2) + blue; - if(col < width) { - gl2psGetRGB(im, col, row, &dr, &dg, &db); - } - else { - dr = dg = db = 0; - } - col++; - red = (unsigned char)(3. * dr); - green = (unsigned char)(3. * dg); - blue = (unsigned char)(3. * db); - b = (b<<2) + red; - b = (b<<2) + green; - gl2psWriteByte(b); - b = 0; - icase++; - } - else if(icase == 3) { - b = blue; - if(col < width) { - gl2psGetRGB(im, col, row, &dr, &dg, &db); - } - else { - dr = dg = db = 0; - } - col++; - red = (unsigned char)(3. * dr); - green = (unsigned char)(3. * dg); - blue = (unsigned char)(3. * db); - b = (b<<2) + red; - b = (b<<2) + green; - b = (b<<2) + blue; - gl2psWriteByte(b); - b = 0; - icase = 1; - } - } - gl2psPrintf("\n"); - } - } - else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */ - nrgb = width * 3; - nbits = nrgb * nbit; - nbyte = nbits / 8; - if((nbyte * 8) != nbits) nbyte++; - gl2psPrintf("/rgbstr %d string def\n", nbyte); - gl2psPrintf("%d %d %d\n", width, height, nbit); - gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); - gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n"); - gl2psPrintf("false 3\n"); - gl2psPrintf("colorimage\n"); - for(row = 0; row < height; row++){ - col = 0; - icase = 1; - for(ibyte = 0; ibyte < nbyte; ibyte++){ - if(icase == 1) { - if(col < width) { - gl2psGetRGB(im, col, row, &dr, &dg, &db); - } - else { - dr = dg = db = 0; - } - col++; - red = (unsigned char)(15. * dr); - green = (unsigned char)(15. * dg); - gl2psPrintf("%x%x", red, green); - icase++; - } - else if(icase == 2) { - blue = (unsigned char)(15. * db); - if(col < width) { - gl2psGetRGB(im, col, row, &dr, &dg, &db); - } - else { - dr = dg = db = 0; - } - col++; - red = (unsigned char)(15. * dr); - gl2psPrintf("%x%x", blue, red); - icase++; - } - else if(icase == 3) { - green = (unsigned char)(15. * dg); - blue = (unsigned char)(15. * db); - gl2psPrintf("%x%x", green, blue); - icase = 1; - } - } - gl2psPrintf("\n"); - } - } - else{ /* 8 bit for r and g and b */ - nbyte = width * 3; - gl2psPrintf("/rgbstr %d string def\n", nbyte); - gl2psPrintf("%d %d %d\n", width, height, 8); - gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); - gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n"); - gl2psPrintf("false 3\n"); - gl2psPrintf("colorimage\n"); - for(row = 0; row < height; row++){ - for(col = 0; col < width; col++){ - gl2psGetRGB(im, col, row, &dr, &dg, &db); - red = (unsigned char)(255. * dr); - gl2psWriteByte(red); - green = (unsigned char)(255. * dg); - gl2psWriteByte(green); - blue = (unsigned char)(255. * db); - gl2psWriteByte(blue); - } - gl2psPrintf("\n"); - } - } - - gl2psPrintf("grestore\n"); -} - -static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y, - GLsizei width, GLsizei height, - const unsigned char *imagemap){ - int i, size; - - if((width <= 0) || (height <= 0)) return; - - size = height + height * (width - 1) / 8; - - gl2psPrintf("gsave\n"); - gl2psPrintf("%.2f %.2f translate\n", x, y); - gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height); - gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height); - for(i = 0; i < size; i++){ - gl2psWriteByte(*imagemap); - imagemap++; - } - gl2psPrintf(">} imagemask\ngrestore\n"); -} - -static void gl2psPrintPostScriptHeader(void) -{ - time_t now; - - /* Since compression is not part of the PostScript standard, - compressed PostScript files are just gzipped PostScript files - ("ps.gz" or "eps.gz") */ - gl2psPrintGzipHeader(); - - time(&now); - - if(gl2ps->format == GL2PS_PS){ - gl2psPrintf("%%!PS-Adobe-3.0\n"); - } - else{ - gl2psPrintf("%%!PS-Adobe-3.0 EPSF-3.0\n"); - } - - gl2psPrintf("%%%%Title: %s\n" - "%%%%Creator: GL2PS %d.%d.%d%s, %s\n" - "%%%%For: %s\n" - "%%%%CreationDate: %s" - "%%%%LanguageLevel: 3\n" - "%%%%DocumentData: Clean7Bit\n" - "%%%%Pages: 1\n", - gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, - GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, - gl2ps->producer, ctime(&now)); - - if(gl2ps->format == GL2PS_PS){ - gl2psPrintf("%%%%Orientation: %s\n" - "%%%%DocumentMedia: Default %d %d 0 () ()\n", - (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait", - (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : - (int)gl2ps->viewport[2], - (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : - (int)gl2ps->viewport[3]); - } - - gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n" - "%%%%EndComments\n", - (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : - (int)gl2ps->viewport[0], - (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] : - (int)gl2ps->viewport[1], - (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : - (int)gl2ps->viewport[2], - (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : - (int)gl2ps->viewport[3]); - - /* RGB color: r g b C (replace C by G in output to change from rgb to gray) - Grayscale: r g b G - Font choose: size fontname FC - Text string: (string) x y size fontname S?? - Rotated text string: (string) angle x y size fontname S??R - Point primitive: x y size P - Line width: width W - Line start: x y LS - Line joining last point: x y L - Line end: x y LE - Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T - Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */ - - gl2psPrintf("%%%%BeginProlog\n" - "/gl2psdict 64 dict def gl2psdict begin\n" - "0 setlinecap 0 setlinejoin\n" - "/tryPS3shading %s def %% set to false to force subdivision\n" - "/rThreshold %g def %% red component subdivision threshold\n" - "/gThreshold %g def %% green component subdivision threshold\n" - "/bThreshold %g def %% blue component subdivision threshold\n", - (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true", - gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]); - - gl2psPrintf("/BD { bind def } bind def\n" - "/C { setrgbcolor } BD\n" - "/G { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n" - "/W { setlinewidth } BD\n"); - - gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n" - "/SW { dup stringwidth pop } BD\n" - "/S { FC moveto show } BD\n" - "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n" - "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n" - "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n" - "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n" - "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n" - "/STL{ FC moveto 0 SH neg rmoveto show } BD\n" - "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n" - "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n"); - - /* rotated text routines: same nameanem with R appended */ - - gl2psPrintf("/FCT { FC translate 0 0 } BD\n" - "/SR { gsave FCT moveto rotate show grestore } BD\n" - "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n" - "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n" - "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n"); - gl2psPrintf("/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n" - "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n" - "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n" - "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n" - "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n"); - - gl2psPrintf("/P { newpath 0.0 360.0 arc closepath fill } BD\n" - "/LS { newpath moveto } BD\n" - "/L { lineto } BD\n" - "/LE { lineto stroke } BD\n" - "/T { newpath moveto lineto lineto closepath fill } BD\n"); - - /* Smooth-shaded triangle with PostScript level 3 shfill operator: - x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */ - - gl2psPrintf("/STshfill {\n" - " /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n" - " /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n" - " /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n" - " gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n" - " /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n" - " shfill grestore } BD\n"); - - /* Flat-shaded triangle with middle color: - x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */ - - gl2psPrintf(/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */ - "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */ - /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */ - " 3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */ - /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */ - " 3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */ - /* stack : x3 y3 x2 y2 x1 y1 r g b */ - " C T } BD\n"); - - /* Split triangle in four sub-triangles (at sides middle points) and call the - STnoshfill procedure on each, interpolating the colors in RGB space: - x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit - (in procedure comments key: (Vi) = xi yi ri gi bi) */ - - gl2psPrintf("/STsplit {\n" - " 4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */ - " 4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */ - " 4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */ - " 4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */ - " 4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */ - " 5 copy 5 copy 25 15 roll\n"); - - /* at this point, stack = (V3) (V13) (V13) (V13) (V2) (V1) */ - - gl2psPrintf(" 9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */ - " 9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */ - " 9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */ - " 9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */ - " 9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */ - " 5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n"); - - /* stack = (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */ - - gl2psPrintf(" 4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */ - " 4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */ - " 4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */ - " 4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */ - " 4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */ - " 5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n"); - - /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */ - - gl2psPrintf(" STnoshfill STnoshfill STnoshfill STnoshfill } BD\n"); - - /* Gouraud shaded triangle using recursive subdivision until the difference - between corner colors does not exceed the thresholds: - x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill */ - - gl2psPrintf("/STnoshfill {\n" - " 2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */ - " { STsplit }\n" - " { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */ - " { STsplit }\n" - " { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */ - " { STsplit }\n" - " { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */ - " { STsplit }\n" - " { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */ - " { STsplit }\n" - " { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */ - " { STsplit }\n" - " { 7 index 13 index sub abs rThreshold gt\n"); /* |r2-r3|>rht */ - gl2psPrintf(" { STsplit }\n" - " { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */ - " { STsplit }\n" - " { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */ - " { STsplit }\n" - " { Tm }\n" /* all colors sufficiently similar */ - " ifelse }\n" - " ifelse }\n" - " ifelse }\n" - " ifelse }\n" - " ifelse }\n" - " ifelse }\n" - " ifelse }\n" - " ifelse }\n" - " ifelse } BD\n"); - - gl2psPrintf("tryPS3shading\n" - "{ /shfill where\n" - " { /ST { STshfill } BD }\n" - " { /ST { STnoshfill } BD }\n" - " ifelse }\n" - "{ /ST { STnoshfill } BD }\n" - "ifelse\n"); - - gl2psPrintf("end\n" - "%%%%EndProlog\n" - "%%%%BeginSetup\n" - "/DeviceRGB setcolorspace\n" - "gl2psdict begin\n" - "%%%%EndSetup\n" - "%%%%Page: 1 1\n" - "%%%%BeginPageSetup\n"); - - if(gl2ps->options & GL2PS_LANDSCAPE){ - gl2psPrintf("%d 0 translate 90 rotate\n", - (int)gl2ps->viewport[3]); - } - - gl2psPrintf("%%%%EndPageSetup\n" - "mark\n" - "gsave\n" - "1.0 1.0 scale\n"); - - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - gl2psPrintf("%g %g %g C\n" - "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" - "closepath fill\n", - gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2], - (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], - (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], - (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]); - } -} - -static void gl2psPrintPostScriptColor(GL2PSrgba rgba) -{ - if(!gl2psSameColor(gl2ps->lastrgba, rgba)){ - gl2psSetLastColor(rgba); - gl2psPrintf("%g %g %g C\n", rgba[0], rgba[1], rgba[2]); - } -} - -static void gl2psResetPostScriptColor(void) -{ - gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.; -} - -static void gl2psEndPostScriptLine(void) -{ - int i; - if(gl2ps->lastvertex.rgba[0] >= 0.){ - gl2psPrintf("%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]); - for(i = 0; i < 3; i++) - gl2ps->lastvertex.xyz[i] = -1.; - for(i = 0; i < 4; i++) - gl2ps->lastvertex.rgba[i] = -1.; - } -} - -static void gl2psParseStipplePattern(GLushort pattern, GLint factor, - int *nb, int array[10]) -{ - int i, n; - int on[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int off[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - char tmp[16]; - - /* extract the 16 bits from the OpenGL stipple pattern */ - for(n = 15; n >= 0; n--){ - tmp[n] = (char)(pattern & 0x01); - pattern >>= 1; - } - /* compute the on/off pixel sequence */ - n = 0; - for(i = 0; i < 8; i++){ - while(n < 16 && !tmp[n]){ off[i]++; n++; } - while(n < 16 && tmp[n]){ on[i]++; n++; } - if(n >= 15){ i++; break; } - } - - /* store the on/off array from right to left, starting with off - pixels. The PostScript specification allows for at most 11 - elements in the on/off array, so we limit ourselves to 5 on/off - couples (our longest possible array is thus [on4 off4 on3 off3 - on2 off2 on1 off1 on0 off0]) */ - *nb = 0; - for(n = i - 1; n >= 0; n--){ - array[(*nb)++] = factor * on[n]; - array[(*nb)++] = factor * off[n]; - if(*nb == 10) break; - } -} - -static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, const char *str) -{ - int len = 0, i, n, array[10]; - - if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor) - return 0; - - gl2ps->lastpattern = pattern; - gl2ps->lastfactor = factor; - - if(!pattern || !factor){ - /* solid line */ - len += gl2psPrintf("[] 0 %s\n", str); - } - else{ - gl2psParseStipplePattern(pattern, factor, &n, array); - len += gl2psPrintf("["); - for(i = 0; i < n; i++){ - if(i) len += gl2psPrintf(" "); - len += gl2psPrintf("%d", array[i]); - } - len += gl2psPrintf("] 0 %s\n", str); - } - - return len; -} - -static void gl2psPrintPostScriptPrimitive(void *data) -{ - int newline; - GL2PSprimitive *prim; - - prim = *(GL2PSprimitive**)data; - - if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return; - - /* Every effort is made to draw lines as connected segments (i.e., - using a single PostScript path): this is the only way to get nice - line joins and to not restart the stippling for every line - segment. So if the primitive to print is not a line we must first - finish the current line (if any): */ - if(prim->type != GL2PS_LINE) gl2psEndPostScriptLine(); - - switch(prim->type){ - case GL2PS_POINT : - gl2psPrintPostScriptColor(prim->verts[0].rgba); - gl2psPrintf("%g %g %g P\n", - prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width); - break; - case GL2PS_LINE : - if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) || - !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) || - gl2ps->lastlinewidth != prim->width || - gl2ps->lastpattern != prim->pattern || - gl2ps->lastfactor != prim->factor){ - /* End the current line if the new segment does not start where - the last one ended, or if the color, the width or the - stippling have changed (multi-stroking lines with changing - colors is necessary until we use /shfill for lines; - unfortunately this means that at the moment we can screw up - line stippling for smooth-shaded lines) */ - gl2psEndPostScriptLine(); - newline = 1; - } - else{ - newline = 0; - } - if(gl2ps->lastlinewidth != prim->width){ - gl2ps->lastlinewidth = prim->width; - gl2psPrintf("%g W\n", gl2ps->lastlinewidth); - } - gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash"); - gl2psPrintPostScriptColor(prim->verts[0].rgba); - gl2psPrintf("%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1], - newline ? "LS" : "L"); - gl2ps->lastvertex = prim->verts[1]; - break; - case GL2PS_TRIANGLE : - if(!gl2psVertsSameColor(prim)){ - gl2psResetPostScriptColor(); - gl2psPrintf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n", - prim->verts[2].xyz[0], prim->verts[2].xyz[1], - prim->verts[2].rgba[0], prim->verts[2].rgba[1], - prim->verts[2].rgba[2], prim->verts[1].xyz[0], - prim->verts[1].xyz[1], prim->verts[1].rgba[0], - prim->verts[1].rgba[1], prim->verts[1].rgba[2], - prim->verts[0].xyz[0], prim->verts[0].xyz[1], - prim->verts[0].rgba[0], prim->verts[0].rgba[1], - prim->verts[0].rgba[2]); - } - else{ - gl2psPrintPostScriptColor(prim->verts[0].rgba); - gl2psPrintf("%g %g %g %g %g %g T\n", - prim->verts[2].xyz[0], prim->verts[2].xyz[1], - prim->verts[1].xyz[0], prim->verts[1].xyz[1], - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - } - break; - case GL2PS_QUADRANGLE : - gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print"); - break; - case GL2PS_PIXMAP : - gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1], - prim->data.image); - break; - case GL2PS_IMAGEMAP : - if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){ - gl2psPrintPostScriptColor(prim->verts[0].rgba); - gl2psPrintPostScriptImagemap(prim->data.image->pixels[0], - prim->data.image->pixels[1], - prim->data.image->width, prim->data.image->height, - (const unsigned char*)(&(prim->data.image->pixels[2]))); - prim->data.image->type = GL2PS_IMAGEMAP_WRITTEN; - } - break; - case GL2PS_TEXT : - gl2psPrintPostScriptColor(prim->verts[0].rgba); - gl2psPrintf("(%s) ", prim->data.text->str); - if(prim->data.text->angle) - gl2psPrintf("%g ", prim->data.text->angle); - gl2psPrintf("%g %g %d /%s ", - prim->verts[0].xyz[0], prim->verts[0].xyz[1], - prim->data.text->fontsize, prim->data.text->fontname); - switch(prim->data.text->alignment){ - case GL2PS_TEXT_C: - gl2psPrintf(prim->data.text->angle ? "SCCR\n" : "SCC\n"); - break; - case GL2PS_TEXT_CL: - gl2psPrintf(prim->data.text->angle ? "SCLR\n" : "SCL\n"); - break; - case GL2PS_TEXT_CR: - gl2psPrintf(prim->data.text->angle ? "SCRR\n" : "SCR\n"); - break; - case GL2PS_TEXT_B: - gl2psPrintf(prim->data.text->angle ? "SBCR\n" : "SBC\n"); - break; - case GL2PS_TEXT_BR: - gl2psPrintf(prim->data.text->angle ? "SBRR\n" : "SBR\n"); - break; - case GL2PS_TEXT_T: - gl2psPrintf(prim->data.text->angle ? "STCR\n" : "STC\n"); - break; - case GL2PS_TEXT_TL: - gl2psPrintf(prim->data.text->angle ? "STLR\n" : "STL\n"); - break; - case GL2PS_TEXT_TR: - gl2psPrintf(prim->data.text->angle ? "STRR\n" : "STR\n"); - break; - case GL2PS_TEXT_BL: - default: - gl2psPrintf(prim->data.text->angle ? "SR\n" : "S\n"); - break; - } - break; - case GL2PS_SPECIAL : - /* alignment contains the format for which the special output text - is intended */ - if(prim->data.text->alignment == GL2PS_PS || - prim->data.text->alignment == GL2PS_EPS) - gl2psPrintf("%s\n", prim->data.text->str); - break; - default : - break; - } -} - -static void gl2psPrintPostScriptFooter(void) -{ - gl2psPrintf("grestore\n" - "showpage\n" - "cleartomark\n" - "%%%%PageTrailer\n" - "%%%%Trailer\n" - "end\n" - "%%%%EOF\n"); - - gl2psPrintGzipFooter(); -} - -static void gl2psPrintPostScriptBeginViewport(GLint viewport[4]) -{ - GLint index; - GLfloat rgba[4]; - int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; - - glRenderMode(GL_FEEDBACK); - - if(gl2ps->header){ - gl2psPrintPostScriptHeader(); - gl2ps->header = GL_FALSE; - } - - gl2psPrintf("gsave\n" - "1.0 1.0 scale\n"); - - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ - glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); - } - else{ - glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); - rgba[0] = gl2ps->colormap[index][0]; - rgba[1] = gl2ps->colormap[index][1]; - rgba[2] = gl2ps->colormap[index][2]; - rgba[3] = 1.0F; - } - gl2psPrintf("%g %g %g C\n" - "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" - "closepath fill\n", - rgba[0], rgba[1], rgba[2], - x, y, x+w, y, x+w, y+h, x, y+h); - } - - gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" - "closepath clip\n", - x, y, x+w, y, x+w, y+h, x, y+h); - -} - -static GLint gl2psPrintPostScriptEndViewport(void) -{ - GLint res; - - res = gl2psPrintPrimitives(); - gl2psPrintf("grestore\n"); - return res; -} - -static void gl2psPrintPostScriptFinalPrimitive(void) -{ - /* End any remaining line, if any */ - gl2psEndPostScriptLine(); -} - -/* definition of the PostScript and Encapsulated PostScript backends */ - -static GL2PSbackend gl2psPS = { - gl2psPrintPostScriptHeader, - gl2psPrintPostScriptFooter, - gl2psPrintPostScriptBeginViewport, - gl2psPrintPostScriptEndViewport, - gl2psPrintPostScriptPrimitive, - gl2psPrintPostScriptFinalPrimitive, - "ps", - "Postscript" -}; - -static GL2PSbackend gl2psEPS = { - gl2psPrintPostScriptHeader, - gl2psPrintPostScriptFooter, - gl2psPrintPostScriptBeginViewport, - gl2psPrintPostScriptEndViewport, - gl2psPrintPostScriptPrimitive, - gl2psPrintPostScriptFinalPrimitive, - "eps", - "Encapsulated Postscript" -}; - -/********************************************************************* - * - * LaTeX routines - * - *********************************************************************/ - -static void gl2psPrintTeXHeader(void) -{ - char name[256]; - time_t now; - int i; - - if(gl2ps->filename && strlen(gl2ps->filename) < 256){ - for(i = strlen(gl2ps->filename)-1; i >= 0; i--){ - if(gl2ps->filename[i] == '.'){ - strncpy(name, gl2ps->filename, i); - name[i] = '\0'; - break; - } - } - if(i <= 0) strcpy(name, gl2ps->filename); - } - else{ - strcpy(name, "untitled"); - } - - time(&now); - - fprintf(gl2ps->stream, - "%% Title: %s\n" - "%% Creator: GL2PS %d.%d.%d%s, %s\n" - "%% For: %s\n" - "%% CreationDate: %s", - gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, - GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, - gl2ps->producer, ctime(&now)); - - fprintf(gl2ps->stream, - "\\setlength{\\unitlength}{1pt}\n" - "\\begin{picture}(0,0)\n" - "\\includegraphics{%s}\n" - "\\end{picture}%%\n" - "%s\\begin{picture}(%d,%d)(0,0)\n", - name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "", - (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); -} - -static void gl2psPrintTeXPrimitive(void *data) -{ - GL2PSprimitive *prim; - - prim = *(GL2PSprimitive**)data; - - switch(prim->type){ - case GL2PS_TEXT : - fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont", - prim->data.text->fontsize); - fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)", - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - switch(prim->data.text->alignment){ - case GL2PS_TEXT_C: - fprintf(gl2ps->stream, "{"); - break; - case GL2PS_TEXT_CL: - fprintf(gl2ps->stream, "[l]{"); - break; - case GL2PS_TEXT_CR: - fprintf(gl2ps->stream, "[r]{"); - break; - case GL2PS_TEXT_B: - fprintf(gl2ps->stream, "[b]{"); - break; - case GL2PS_TEXT_BR: - fprintf(gl2ps->stream, "[br]{"); - break; - case GL2PS_TEXT_T: - fprintf(gl2ps->stream, "[t]{"); - break; - case GL2PS_TEXT_TL: - fprintf(gl2ps->stream, "[tl]{"); - break; - case GL2PS_TEXT_TR: - fprintf(gl2ps->stream, "[tr]{"); - break; - case GL2PS_TEXT_BL: - default: - fprintf(gl2ps->stream, "[bl]{"); - break; - } - if(prim->data.text->angle) - fprintf(gl2ps->stream, "\\rotatebox{%g}{", prim->data.text->angle); - fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}", - prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2], - prim->data.text->str); - if(prim->data.text->angle) - fprintf(gl2ps->stream, "}"); - fprintf(gl2ps->stream, "}}\n"); - break; - case GL2PS_SPECIAL : - /* alignment contains the format for which the special output text - is intended */ - if (prim->data.text->alignment == GL2PS_TEX) - fprintf(gl2ps->stream, "%s\n", prim->data.text->str); - break; - default : - break; - } -} - -static void gl2psPrintTeXFooter(void) -{ - fprintf(gl2ps->stream, "\\end{picture}%s\n", - (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : ""); -} - -static void gl2psPrintTeXBeginViewport(GLint /*viewport*/[4]) -{ - glRenderMode(GL_FEEDBACK); - - if(gl2ps->header){ - gl2psPrintTeXHeader(); - gl2ps->header = GL_FALSE; - } -} - -static GLint gl2psPrintTeXEndViewport(void) -{ - return gl2psPrintPrimitives(); -} - -static void gl2psPrintTeXFinalPrimitive(void) -{ -} - -/* definition of the LaTeX backend */ - -static GL2PSbackend gl2psTEX = { - gl2psPrintTeXHeader, - gl2psPrintTeXFooter, - gl2psPrintTeXBeginViewport, - gl2psPrintTeXEndViewport, - gl2psPrintTeXPrimitive, - gl2psPrintTeXFinalPrimitive, - "tex", - "LaTeX text" -}; - -/********************************************************************* - * - * PDF routines - * - *********************************************************************/ - -static int gl2psPrintPDFCompressorType(void) -{ -#if defined(GL2PS_HAVE_ZLIB) - if(gl2ps->options & GL2PS_COMPRESS){ - return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n"); - } -#endif - return 0; -} - -static int gl2psPrintPDFStrokeColor(GL2PSrgba rgba) -{ - int i, offs = 0; - - gl2psSetLastColor(rgba); - for(i = 0; i < 3; ++i){ - if(GL2PS_ZERO(rgba[i])) - offs += gl2psPrintf("%.0f ", 0.); - else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ - offs += gl2psPrintf("%f ", rgba[i]); - else - offs += gl2psPrintf("%g ", rgba[i]); - } - offs += gl2psPrintf("RG\n"); - return offs; -} - -static int gl2psPrintPDFFillColor(GL2PSrgba rgba) -{ - int i, offs = 0; - - for(i = 0; i < 3; ++i){ - if(GL2PS_ZERO(rgba[i])) - offs += gl2psPrintf("%.0f ", 0.); - else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ - offs += gl2psPrintf("%f ", rgba[i]); - else - offs += gl2psPrintf("%g ", rgba[i]); - } - offs += gl2psPrintf("rg\n"); - return offs; -} - -static int gl2psPrintPDFLineWidth(GLfloat lw) -{ - if(GL2PS_ZERO(lw)) - return gl2psPrintf("%.0f w\n", 0.); - else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */ - return gl2psPrintf("%f w\n", lw); - else - return gl2psPrintf("%g w\n", lw); -} - -static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y) -{ - gl2ps->streamlength += - gl2psPrintf("BT\n" - "/F%d %d Tf\n" - "%f %f Td\n" - "(%s) Tj\n" - "ET\n", - cnt, text->fontsize, x, y, text->str); -} - -static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y) -{ - gl2ps->streamlength += - gl2psPrintf("q\n" - "%d 0 0 %d %f %f cm\n" - "/Im%d Do\n" - "Q\n", - (int)image->width, (int)image->height, x, y, cnt); -} - -static void gl2psPDFstacksInit(void) -{ - gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1; - gl2ps->extgs_stack = 0; - gl2ps->font_stack = 0; - gl2ps->im_stack = 0; - gl2ps->trgroupobjects_stack = 0; - gl2ps->shader_stack = 0; - gl2ps->mshader_stack = 0; -} - -static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro) -{ - if(!gro) - return; - - gro->ptrlist = NULL; - gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno - = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno - = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1; -} - -/* Build up group objects and assign name and object numbers */ - -static void gl2psPDFgroupListInit(void) -{ - int i; - GL2PSprimitive *p = NULL; - GL2PSpdfgroup gro; - int lasttype = GL2PS_NO_TYPE; - GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F}; - GLushort lastpattern = 0; - GLint lastfactor = 0; - GLfloat lastwidth = 1; - GL2PStriangle lastt, tmpt; - int lastTriangleWasNotSimpleWithSameColor = 0; - - if(!gl2ps->pdfprimlist) - return; - - gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup)); - gl2psInitTriangle(&lastt); - - for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){ - p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i); - switch(p->type){ - case GL2PS_PIXMAP: - gl2psPDFgroupObjectInit(&gro); - gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - gro.imno = gl2ps->im_stack++; - gl2psListAdd(gro.ptrlist, &p); - gl2psListAdd(gl2ps->pdfgrouplist, &gro); - break; - case GL2PS_TEXT: - gl2psPDFgroupObjectInit(&gro); - gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - gro.fontno = gl2ps->font_stack++; - gl2psListAdd(gro.ptrlist, &p); - gl2psListAdd(gl2ps->pdfgrouplist, &gro); - break; - case GL2PS_LINE: - if(lasttype != p->type || lastwidth != p->width || - lastpattern != p->pattern || lastfactor != p->factor || - !gl2psSameColor(p->verts[0].rgba, lastrgba)){ - gl2psPDFgroupObjectInit(&gro); - gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - gl2psListAdd(gro.ptrlist, &p); - gl2psListAdd(gl2ps->pdfgrouplist, &gro); - } - else{ - gl2psListAdd(gro.ptrlist, &p); - } - lastpattern = p->pattern; - lastfactor = p->factor; - lastwidth = p->width; - lastrgba[0] = p->verts[0].rgba[0]; - lastrgba[1] = p->verts[0].rgba[1]; - lastrgba[2] = p->verts[0].rgba[2]; - break; - case GL2PS_POINT: - if(lasttype != p->type || lastwidth != p->width || - !gl2psSameColor(p->verts[0].rgba, lastrgba)){ - gl2psPDFgroupObjectInit(&gro); - gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*)); - gl2psListAdd(gro.ptrlist, &p); - gl2psListAdd(gl2ps->pdfgrouplist, &gro); - } - else{ - gl2psListAdd(gro.ptrlist, &p); - } - lastwidth = p->width; - lastrgba[0] = p->verts[0].rgba[0]; - lastrgba[1] = p->verts[0].rgba[1]; - lastrgba[2] = p->verts[0].rgba[2]; - break; - case GL2PS_TRIANGLE: - gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE); - lastTriangleWasNotSimpleWithSameColor = - !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) || - !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba); - if(lasttype == p->type && tmpt.prop == lastt.prop && - lastTriangleWasNotSimpleWithSameColor){ - /* TODO Check here for last alpha */ - gl2psListAdd(gro.ptrlist, &p); - } - else{ - gl2psPDFgroupObjectInit(&gro); - gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); - gl2psListAdd(gro.ptrlist, &p); - gl2psListAdd(gl2ps->pdfgrouplist, &gro); - } - lastt = tmpt; - break; - default: - break; - } - lasttype = p->type; - } -} - -static void gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro) -{ - GL2PStriangle t; - GL2PSprimitive *prim = NULL; - - if(!gro) - return; - - if(!gl2psListNbr(gro->ptrlist)) - return; - - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0); - - if(prim->type != GL2PS_TRIANGLE) - return; - - gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE); - - if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){ - gro->gsno = gl2ps->extgs_stack++; - gro->gsobjno = gl2ps->objects_stack ++; - } - else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){ - gro->gsno = gl2ps->extgs_stack++; - gro->gsobjno = gl2ps->objects_stack++; - gro->trgroupno = gl2ps->trgroupobjects_stack++; - gro->trgroupobjno = gl2ps->objects_stack++; - gro->maskshno = gl2ps->mshader_stack++; - gro->maskshobjno = gl2ps->objects_stack++; - } - else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){ - gro->shno = gl2ps->shader_stack++; - gro->shobjno = gl2ps->objects_stack++; - } - else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){ - gro->gsno = gl2ps->extgs_stack++; - gro->gsobjno = gl2ps->objects_stack++; - gro->shno = gl2ps->shader_stack++; - gro->shobjno = gl2ps->objects_stack++; - } - else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){ - gro->gsno = gl2ps->extgs_stack++; - gro->gsobjno = gl2ps->objects_stack++; - gro->shno = gl2ps->shader_stack++; - gro->shobjno = gl2ps->objects_stack++; - gro->trgroupno = gl2ps->trgroupobjects_stack++; - gro->trgroupobjno = gl2ps->objects_stack++; - gro->maskshno = gl2ps->mshader_stack++; - gro->maskshobjno = gl2ps->objects_stack++; - } -} - -/* Main stream data */ - -static void gl2psPDFgroupListWriteMainStream(void) -{ - int i, j, lastel; - GL2PSprimitive *prim = NULL, *prev = NULL; - GL2PSpdfgroup *gro; - GL2PStriangle t; - - if(!gl2ps->pdfgrouplist) - return; - - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); - - lastel = gl2psListNbr(gro->ptrlist) - 1; - if(lastel < 0) - continue; - - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0); - - switch(prim->type){ - case GL2PS_POINT: - gl2ps->streamlength += gl2psPrintf("1 J\n"); - gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width); - gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); - for(j = 0; j <= lastel; ++j){ - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2ps->streamlength += - gl2psPrintf("%f %f m %f %f l\n", - prim->verts[0].xyz[0], prim->verts[0].xyz[1], - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - } - gl2ps->streamlength += gl2psPrintf("S\n"); - gl2ps->streamlength += gl2psPrintf("0 J\n"); - break; - case GL2PS_LINE: - /* We try to use as few paths as possible to draw lines, in - order to get nice stippling even when the individual segments - are smaller than the stipple */ - gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width); - gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); - gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d"); - /* start new path */ - gl2ps->streamlength += - gl2psPrintf("%f %f m\n", - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - - for(j = 1; j <= lastel; ++j){ - prev = prim; - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - if(!gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){ - /* the starting point of the new segment does not match the - end point of the previous line, so we end the current - path and start a new one */ - gl2ps->streamlength += - gl2psPrintf("%f %f l\n", - prev->verts[1].xyz[0], prev->verts[1].xyz[1]); - gl2ps->streamlength += - gl2psPrintf("%f %f m\n", - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - } - else{ - /* the two segements are connected, so we just append to the - current path */ - gl2ps->streamlength += - gl2psPrintf("%f %f l\n", - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - } - } - /* end last path */ - gl2ps->streamlength += - gl2psPrintf("%f %f l\n", - prim->verts[1].xyz[0], prim->verts[1].xyz[1]); - gl2ps->streamlength += gl2psPrintf("S\n"); - break; - case GL2PS_TRIANGLE: - gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE); - gl2psSortOutTrianglePDFgroup(gro); - - /* No alpha and const color: Simple PDF draw orders */ - if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){ - gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba); - for(j = 0; j <= lastel; ++j){ - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE); - gl2ps->streamlength - += gl2psPrintf("%f %f m\n" - "%f %f l\n" - "%f %f l\n" - "h f\n", - t.vertex[0].xyz[0], t.vertex[0].xyz[1], - t.vertex[1].xyz[0], t.vertex[1].xyz[1], - t.vertex[2].xyz[0], t.vertex[2].xyz[1]); - } - } - /* Const alpha < 1 and const color: Simple PDF draw orders - and an extra extended Graphics State for the alpha const */ - else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){ - gl2ps->streamlength += gl2psPrintf("q\n" - "/GS%d gs\n", - gro->gsno); - gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba); - for(j = 0; j <= lastel; ++j){ - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE); - gl2ps->streamlength - += gl2psPrintf("%f %f m\n" - "%f %f l\n" - "%f %f l\n" - "h f\n", - t.vertex[0].xyz[0], t.vertex[0].xyz[1], - t.vertex[1].xyz[0], t.vertex[1].xyz[1], - t.vertex[2].xyz[0], t.vertex[2].xyz[1]); - } - gl2ps->streamlength += gl2psPrintf("Q\n"); - } - /* Variable alpha and const color: Simple PDF draw orders - and an extra extended Graphics State + Xobject + Shader - object for the alpha mask */ - else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){ - gl2ps->streamlength += gl2psPrintf("q\n" - "/GS%d gs\n" - "/TrG%d Do\n", - gro->gsno, gro->trgroupno); - gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba); - for(j = 0; j <= lastel; ++j){ - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE); - gl2ps->streamlength - += gl2psPrintf("%f %f m\n" - "%f %f l\n" - "%f %f l\n" - "h f\n", - t.vertex[0].xyz[0], t.vertex[0].xyz[1], - t.vertex[1].xyz[0], t.vertex[1].xyz[1], - t.vertex[2].xyz[0], t.vertex[2].xyz[1]); - } - gl2ps->streamlength += gl2psPrintf("Q\n"); - } - /* Variable color and no alpha: Shader Object for the colored - triangle(s) */ - else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){ - gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno); - } - /* Variable color and const alpha < 1: Shader Object for the - colored triangle(s) and an extra extended Graphics State - for the alpha const */ - else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){ - gl2ps->streamlength += gl2psPrintf("q\n" - "/GS%d gs\n" - "/Sh%d sh\n" - "Q\n", - gro->gsno, gro->shno); - } - /* Variable alpha and color: Shader Object for the colored - triangle(s) and an extra extended Graphics State - + Xobject + Shader object for the alpha mask */ - else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){ - gl2ps->streamlength += gl2psPrintf("q\n" - "/GS%d gs\n" - "/TrG%d Do\n" - "/Sh%d sh\n" - "Q\n", - gro->gsno, gro->trgroupno, gro->shno); - } - break; - case GL2PS_PIXMAP: - for(j = 0; j <= lastel; ++j){ - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0], - prim->verts[0].xyz[1]); - } - break; - case GL2PS_TEXT: - for(j = 0; j <= lastel; ++j){ - prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba); - gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0], - prim->verts[0].xyz[1]); - } - break; - default: - break; - } - } -} - -/* Graphics State names */ - -static int gl2psPDFgroupListWriteGStateResources(void) -{ - GL2PSpdfgroup *gro; - int offs = 0; - int i; - - offs += fprintf(gl2ps->stream, - "/ExtGState\n" - "<<\n" - "/GSa 7 0 R\n"); - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); - if(gro->gsno >= 0) - offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno); - } - offs += fprintf(gl2ps->stream, ">>\n"); - return offs; -} - -/* Main Shader names */ - -static int gl2psPDFgroupListWriteShaderResources(void) -{ - GL2PSpdfgroup *gro; - int offs = 0; - int i; - - offs += fprintf(gl2ps->stream, - "/Shading\n" - "<<\n"); - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); - if(gro->shno >= 0) - offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno); - if(gro->maskshno >= 0) - offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno); - } - offs += fprintf(gl2ps->stream,">>\n"); - return offs; -} - -/* Images & Mask Shader XObject names */ - -static int gl2psPDFgroupListWriteXObjectResources(void) -{ - int i; - GL2PSprimitive *p = NULL; - GL2PSpdfgroup *gro; - int offs = 0; - - offs += fprintf(gl2ps->stream, - "/XObject\n" - "<<\n"); - - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); - if(!gl2psListNbr(gro->ptrlist)) - continue; - p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0); - switch(p->type){ - case GL2PS_PIXMAP: - gro->imobjno = gl2ps->objects_stack++; - if(GL_RGBA == p->data.image->format) /* reserve one object for image mask */ - gl2ps->objects_stack++; - offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", gro->imno, gro->imobjno); - case GL2PS_TRIANGLE: - if(gro->trgroupno >=0) - offs += fprintf(gl2ps->stream, "/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno); - break; - default: - break; - } - } - offs += fprintf(gl2ps->stream,">>\n"); - return offs; -} - -/* Font names */ - -static int gl2psPDFgroupListWriteFontResources(void) -{ - int i; - GL2PSpdfgroup *gro; - int offs = 0; - - offs += fprintf(gl2ps->stream, "/Font\n<<\n"); - - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); - if(gro->fontno < 0) - continue; - gro->fontobjno = gl2ps->objects_stack++; - offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", gro->fontno, gro->fontobjno); - } - offs += fprintf(gl2ps->stream, ">>\n"); - - return offs; -} - -static void gl2psPDFgroupListDelete(void) -{ - int i; - GL2PSpdfgroup *gro = NULL; - - if(!gl2ps->pdfgrouplist) - return; - - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i); - gl2psListDelete(gro->ptrlist); - } - - gl2psListDelete(gl2ps->pdfgrouplist); - gl2ps->pdfgrouplist = NULL; -} - -/* Print 1st PDF object - file info */ - -static int gl2psPrintPDFInfo(void) -{ - int offs; - time_t now; - struct tm *newtime; - - time(&now); - newtime = gmtime(&now); - - offs = fprintf(gl2ps->stream, - "1 0 obj\n" - "<<\n" - "/Title (%s)\n" - "/Creator (GL2PS %d.%d.%d%s, %s)\n" - "/Producer (%s)\n", - gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, - GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, - gl2ps->producer); - - if(!newtime){ - offs += fprintf(gl2ps->stream, - ">>\n" - "endobj\n"); - return offs; - } - - offs += fprintf(gl2ps->stream, - "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n" - ">>\n" - "endobj\n", - newtime->tm_year+1900, - newtime->tm_mon+1, - newtime->tm_mday, - newtime->tm_hour, - newtime->tm_min, - newtime->tm_sec); - return offs; -} - -/* Create catalog and page structure - 2nd and 3th PDF object */ - -static int gl2psPrintPDFCatalog(void) -{ - return fprintf(gl2ps->stream, - "2 0 obj\n" - "<<\n" - "/Type /Catalog\n" - "/Pages 3 0 R\n" - ">>\n" - "endobj\n"); -} - -static int gl2psPrintPDFPages(void) -{ - return fprintf(gl2ps->stream, - "3 0 obj\n" - "<<\n" - "/Type /Pages\n" - "/Kids [6 0 R]\n" - "/Count 1\n" - ">>\n" - "endobj\n"); -} - -/* Open stream for data - graphical objects, fonts etc. PDF object 4 */ - -static int gl2psOpenPDFDataStream(void) -{ - int offs = 0; - - offs += fprintf(gl2ps->stream, - "4 0 obj\n" - "<<\n" - "/Length 5 0 R\n" ); - offs += gl2psPrintPDFCompressorType(); - offs += fprintf(gl2ps->stream, - ">>\n" - "stream\n"); - return offs; -} - -/* Stream setup - Graphics state, fill background if allowed */ - -static int gl2psOpenPDFDataStreamWritePreface(void) -{ - int offs; - - offs = gl2psPrintf("/GSa gs\n"); - - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - offs += gl2psPrintPDFFillColor(gl2ps->bgcolor); - offs += gl2psPrintf("%d %d %d %d re\n", - (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], - (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); - offs += gl2psPrintf("f\n"); - } - return offs; -} - -/* Use the functions above to create the first part of the PDF*/ - -static void gl2psPrintPDFHeader(void) -{ - int offs = 0; - gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); - gl2psPDFstacksInit(); - - gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack); - -#if defined(GL2PS_HAVE_ZLIB) - if(gl2ps->options & GL2PS_COMPRESS){ - gl2psSetupCompress(); - } -#endif - gl2ps->xreflist[0] = 0; - offs += fprintf(gl2ps->stream, "%%PDF-1.4\n"); - gl2ps->xreflist[1] = offs; - - offs += gl2psPrintPDFInfo(); - gl2ps->xreflist[2] = offs; - - offs += gl2psPrintPDFCatalog(); - gl2ps->xreflist[3] = offs; - - offs += gl2psPrintPDFPages(); - gl2ps->xreflist[4] = offs; - - offs += gl2psOpenPDFDataStream(); - gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */ - gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface(); -} - -/* The central primitive drawing */ - -static void gl2psPrintPDFPrimitive(void *data) -{ - GL2PSprimitive *prim = *(GL2PSprimitive**)data; - - if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) - return; - - prim = gl2psCopyPrimitive(prim); /* deep copy */ - gl2psListAdd(gl2ps->pdfprimlist, &prim); -} - -/* close stream and ... */ - -static int gl2psClosePDFDataStream(void) -{ - int offs = 0; - -#if defined(GL2PS_HAVE_ZLIB) - if(gl2ps->options & GL2PS_COMPRESS){ - if(Z_OK != gl2psDeflate()) - gl2psMsg(GL2PS_ERROR, "Zlib deflate error"); - else - fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream); - gl2ps->streamlength += gl2ps->compress->destLen; - - offs += gl2ps->streamlength; - gl2psFreeCompress(); - } -#endif - - offs += fprintf(gl2ps->stream, - "endstream\n" - "endobj\n"); - return offs; -} - -/* ... write the now known length object */ - -static int gl2psPrintPDFDataStreamLength(int val) -{ - return fprintf(gl2ps->stream, - "5 0 obj\n" - "%d\n" - "endobj\n", val); -} - -/* Put the info created before in PDF objects */ - -static int gl2psPrintPDFOpenPage(void) -{ - int offs; - - /* Write fixed part */ - - offs = fprintf(gl2ps->stream, - "6 0 obj\n" - "<<\n" - "/Type /Page\n" - "/Parent 3 0 R\n" - "/MediaBox [%d %d %d %d]\n", - (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], - (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); - - if(gl2ps->options & GL2PS_LANDSCAPE) - offs += fprintf(gl2ps->stream, "/Rotate -90\n"); - - offs += fprintf(gl2ps->stream, - "/Contents 4 0 R\n" - "/Resources\n" - "<<\n" - "/ProcSet [/PDF /Text /ImageB /ImageC] %%/ImageI\n"); - - return offs; - - /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */ -} - -static int gl2psPDFgroupListWriteVariableResources(void) -{ - int offs = 0; - - /* a) Graphics States for shader alpha masks*/ - offs += gl2psPDFgroupListWriteGStateResources(); - - /* b) Shader and shader masks */ - offs += gl2psPDFgroupListWriteShaderResources(); - - /* c) XObjects (Images & Shader Masks) */ - offs += gl2psPDFgroupListWriteXObjectResources(); - - /* d) Fonts */ - offs += gl2psPDFgroupListWriteFontResources(); - - /* End resources and page */ - offs += fprintf(gl2ps->stream, - ">>\n" - ">>\n" - "endobj\n"); - return offs; -} - -/* Standard Graphics State */ - -static int gl2psPrintPDFGSObject(void) -{ - return fprintf(gl2ps->stream, - "7 0 obj\n" - "<<\n" - "/Type /ExtGState\n" - "/SA false\n" - "/SM 0.02\n" - "/OP false\n" - "/op false\n" - "/OPM 0\n" - "/BG2 /Default\n" - "/UCR2 /Default\n" - "/TR2 /Default\n" - ">>\n" - "endobj\n"); -} - -/* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */ - -static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex, - size_t (*action)(unsigned long data, - size_t size), - GLfloat dx, GLfloat dy, - GLfloat xmin, GLfloat ymin) -{ - int offs = 0; - unsigned long imap; - GLfloat diff; - double dmax = double(~1UL); - char edgeflag = 0; - - /* FIXME: temp bux fix for 64 bit archs: */ - if(sizeof(unsigned long) == 8) dmax = dmax - 2048.; - - offs += (*action)(edgeflag, 1); - - /* The Shader stream in PDF requires to be in a 'big-endian' - order */ - - if(GL2PS_ZERO(dx * dy)){ - offs += (*action)(0, 4); - offs += (*action)(0, 4); - } - else{ - diff = (vertex->xyz[0] - xmin) / dx; - if(diff > 1) - diff = 1.0F; - else if(diff < 0) - diff = 0.0F; - imap = (unsigned long)(diff * dmax); - offs += (*action)(imap, 4); - - diff = (vertex->xyz[1] - ymin) / dy; - if(diff > 1) - diff = 1.0F; - else if(diff < 0) - diff = 0.0F; - imap = (unsigned long)(diff * dmax); - offs += (*action)(imap, 4); - } - - return offs; -} - -/* Put vertex' rgb value (8bit for every component) in shader stream */ - -static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex, - size_t (*action)(unsigned long data, - size_t size)) -{ - int offs = 0; - unsigned long imap; - double dmax = double(~1UL); - - /* FIXME: temp bux fix for 64 bit archs: */ - if(sizeof(unsigned long) == 8) dmax = dmax - 2048.; - - imap = (unsigned long)((vertex->rgba[0]) * dmax); - offs += (*action)(imap, 1); - - imap = (unsigned long)((vertex->rgba[1]) * dmax); - offs += (*action)(imap, 1); - - imap = (unsigned long)((vertex->rgba[2]) * dmax); - offs += (*action)(imap, 1); - - return offs; -} - -/* Put vertex' alpha (8/16bit) in shader stream */ - -static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, - size_t (*action)(unsigned long data, - size_t size), - int sigbyte) -{ - int offs = 0; - unsigned long imap; - double dmax = double(~1UL); - - /* FIXME: temp bux fix for 64 bit archs: */ - if(sizeof(unsigned long) == 8) dmax = dmax - 2048.; - - if(sigbyte != 8 && sigbyte != 16) - sigbyte = 8; - - sigbyte /= 8; - - imap = (unsigned long)((vertex->rgba[3]) * dmax); - - offs += (*action)(imap, sigbyte); - - return offs; -} - -/* Put a triangles raw data in shader stream */ - -static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle, - GLfloat dx, GLfloat dy, - GLfloat xmin, GLfloat ymin, - size_t (*action)(unsigned long data, - size_t size), - int gray) -{ - int i, offs = 0; - GL2PSvertex v; - - if(gray && gray != 8 && gray != 16) - gray = 8; - - for(i = 0; i < 3; ++i){ - offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action, - dx, dy, xmin, ymin); - if(gray){ - v = triangle->vertex[i]; - offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray); - } - else{ - offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action); - } - } - - return offs; -} - -static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax, - GLfloat *ymin, GLfloat *ymax, - GL2PStriangle *triangles, int cnt) -{ - int i, j; - - *xmin = triangles[0].vertex[0].xyz[0]; - *xmax = triangles[0].vertex[0].xyz[0]; - *ymin = triangles[0].vertex[0].xyz[1]; - *ymax = triangles[0].vertex[0].xyz[1]; - - for(i = 0; i < cnt; ++i){ - for(j = 0; j < 3; ++j){ - if(*xmin > triangles[i].vertex[j].xyz[0]) - *xmin = triangles[i].vertex[j].xyz[0]; - if(*xmax < triangles[i].vertex[j].xyz[0]) - *xmax = triangles[i].vertex[j].xyz[0]; - if(*ymin > triangles[i].vertex[j].xyz[1]) - *ymin = triangles[i].vertex[j].xyz[1]; - if(*ymax < triangles[i].vertex[j].xyz[1]) - *ymax = triangles[i].vertex[j].xyz[1]; - } - } -} - -/* Writes shaded triangle - gray == 0 means write RGB triangles - gray == 8 8bit-grayscale (for alpha masks) - gray == 16 16bit-grayscale (for alpha masks) */ - -static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles, - int size, int gray) -{ - int i, offs = 0, vertexbytes, done = 0; - GLfloat xmin, xmax, ymin, ymax; - - switch(gray){ - case 0: - vertexbytes = 1+4+4+1+1+1; - break; - case 8: - vertexbytes = 1+4+4+1; - break; - case 16: - vertexbytes = 1+4+4+2; - break; - default: - gray = 8; - vertexbytes = 1+4+4+1; - break; - } - - gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size); - - offs += fprintf(gl2ps->stream, - "%d 0 obj\n" - "<< " - "/ShadingType 4 " - "/ColorSpace %s " - "/BitsPerCoordinate 32 " - "/BitsPerComponent %d " - "/BitsPerFlag 8 " - "/Decode [%f %f %f %f 0 1 %s] ", - obj, - (gray) ? "/DeviceGray" : "/DeviceRGB", - (gray) ? gray : 8, - xmin, xmax, ymin, ymax, - (gray) ? "" : "0 1 0 1"); - -#if defined(GL2PS_HAVE_ZLIB) - if(gl2ps->options & GL2PS_COMPRESS){ - gl2psAllocCompress(vertexbytes * size * 3); - - for(i = 0; i < size; ++i) - gl2psPrintPDFShaderStreamData(&triangles[i], - xmax-xmin, ymax-ymin, xmin, ymin, - gl2psWriteBigEndianCompress, gray); - - if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){ - offs += gl2psPrintPDFCompressorType(); - offs += fprintf(gl2ps->stream, - "/Length %d " - ">>\n" - "stream\n", - (int)gl2ps->compress->destLen); - offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, - gl2ps->compress->destLen, - 1, gl2ps->stream); - done = 1; - } - gl2psFreeCompress(); - } -#endif - - if(!done){ - /* no compression, or too long after compression, or compress error - -> write non-compressed entry */ - offs += fprintf(gl2ps->stream, - "/Length %d " - ">>\n" - "stream\n", - vertexbytes * 3 * size); - for(i = 0; i < size; ++i) - offs += gl2psPrintPDFShaderStreamData(&triangles[i], - xmax-xmin, ymax-ymin, xmin, ymin, - gl2psWriteBigEndian, gray); - } - - offs += fprintf(gl2ps->stream, - "\nendstream\n" - "endobj\n"); - - return offs; -} - -/* Writes a XObject for a shaded triangle mask */ - -static int gl2psPrintPDFShaderMask(int obj, int childobj) -{ - int offs = 0, len; - - offs += fprintf(gl2ps->stream, - "%d 0 obj\n" - "<<\n" - "/Type /XObject\n" - "/Subtype /Form\n" - "/BBox [ %d %d %d %d ]\n" - "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n" - ">>\n", - obj, - (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], - (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); - constexpr auto length = std::char_traits::length; - len = (childobj>0) - ? length("/TrSh sh\n") + (int)log10((double)childobj)+1 - : length("/TrSh0 sh\n"); - - offs += fprintf(gl2ps->stream, - "/Length %d\n" - ">>\n" - "stream\n", - len); - offs += fprintf(gl2ps->stream, - "/TrSh%d sh\n", - childobj); - offs += fprintf(gl2ps->stream, - "endstream\n" - "endobj\n"); - - return offs; -} - -/* Writes a Extended graphics state for a shaded triangle mask if - simplealpha ist true the childobj argument is ignored and a /ca - statement will be written instead */ - -static int gl2psPrintPDFShaderExtGS(int obj, int childobj) -{ - int offs = 0; - - offs += fprintf(gl2ps->stream, - "%d 0 obj\n" - "<<\n", - obj); - - offs += fprintf(gl2ps->stream, - "/SMask << /S /Alpha /G %d 0 R >> ", - childobj); - - offs += fprintf(gl2ps->stream, - ">>\n" - "endobj\n"); - return offs; -} - -/* a simple graphics state */ - -static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha) -{ - int offs = 0; - - offs += fprintf(gl2ps->stream, - "%d 0 obj\n" - "<<\n" - "/ca %g" - ">>\n" - "endobj\n", - obj, alpha); - return offs; -} - -/* Similar groups of functions for pixmaps and text */ - -static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im, - size_t (*action)(unsigned long data, - size_t size), - int gray) -{ - int x, y; - GLfloat r, g, b, a; - - if(im->format != GL_RGBA && gray) - return 0; - - if(gray && gray !=8 && gray != 16) - gray = 8; - - gray /= 8; - - for(y = 0; y < im->height; ++y){ - for(x = 0; x < im->width; ++x){ - a = gl2psGetRGB(im, x, y, &r, &g, &b); - if(im->format == GL_RGBA && gray){ - (*action)((unsigned long)(a*255) << 24, gray); - } - else{ - (*action)((unsigned long)(r*255) << 24, 1); - (*action)((unsigned long)(g*255) << 24, 1); - (*action)((unsigned long)(b*255) << 24, 1); - } - } - } - - switch(gray){ - case 0: return 3 * im->width * im->height; - case 1: return im->width * im->height; - case 2: return 2 * im->width * im->height; - default: return 3 * im->width * im->height; - } -} - -static int gl2psPrintPDFPixmap(int obj, int childobj, GL2PSimage *im, int gray) -{ - int offs = 0, done = 0, sigbytes = 3; - - if(gray && gray !=8 && gray != 16) - gray = 8; - - if(gray) - sigbytes = gray / 8; - - offs += fprintf(gl2ps->stream, - "%d 0 obj\n" - "<<\n" - "/Type /XObject\n" - "/Subtype /Image\n" - "/Width %d\n" - "/Height %d\n" - "/ColorSpace %s \n" - "/BitsPerComponent 8\n", - obj, - (int)im->width, (int)im->height, - (gray) ? "/DeviceGray" : "/DeviceRGB" ); - if(GL_RGBA == im->format && gray == 0){ - offs += fprintf(gl2ps->stream, - "/SMask %d 0 R\n", - childobj); - } - -#if defined(GL2PS_HAVE_ZLIB) - if(gl2ps->options & GL2PS_COMPRESS){ - gl2psAllocCompress((int)(im->width * im->height * sigbytes)); - - gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray); - - if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){ - offs += gl2psPrintPDFCompressorType(); - offs += fprintf(gl2ps->stream, - "/Length %d " - ">>\n" - "stream\n", - (int)gl2ps->compress->destLen); - offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, - 1, gl2ps->stream); - done = 1; - } - gl2psFreeCompress(); - } -#endif - - if(!done){ - /* no compression, or too long after compression, or compress error - -> write non-compressed entry */ - offs += fprintf(gl2ps->stream, - "/Length %d " - ">>\n" - "stream\n", - (int)(im->width * im->height * sigbytes)); - offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray); - } - - offs += fprintf(gl2ps->stream, - "\nendstream\n" - "endobj\n"); - - return offs; -} - -static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber) -{ - int offs = 0; - - offs += fprintf(gl2ps->stream, - "%d 0 obj\n" - "<<\n" - "/Type /Font\n" - "/Subtype /Type1\n" - "/Name /F%d\n" - "/BaseFont /%s\n" - "/Encoding /MacRomanEncoding\n" - ">>\n" - "endobj\n", - obj, fontnumber, s->fontname); - return offs; -} - -/* Write the physical objects */ - -static int gl2psPDFgroupListWriteObjects(int entryoffs) -{ - int i,j; - GL2PSprimitive *p = NULL; - GL2PSpdfgroup *gro; - int offs = entryoffs; - GL2PStriangle *triangles; - int size = 0; - - if(!gl2ps->pdfgrouplist) - return offs; - - for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ - gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); - if(!gl2psListNbr(gro->ptrlist)) - continue; - p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0); - switch(p->type){ - case GL2PS_POINT: - break; - case GL2PS_LINE: - break; - case GL2PS_TRIANGLE: - size = gl2psListNbr(gro->ptrlist); - triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size); - for(j = 0; j < size; ++j){ - p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); - gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE); - } - if(triangles[0].prop & T_VAR_COLOR){ - gl2ps->xreflist[gro->shobjno] = offs; - offs += gl2psPrintPDFShader(gro->shobjno, triangles, size, 0); - } - if(triangles[0].prop & T_ALPHA_LESS_1){ - gl2ps->xreflist[gro->gsobjno] = offs; - offs += gl2psPrintPDFShaderSimpleExtGS(gro->gsobjno, triangles[0].vertex[0].rgba[3]); - } - if(triangles[0].prop & T_VAR_ALPHA){ - gl2ps->xreflist[gro->gsobjno] = offs; - offs += gl2psPrintPDFShaderExtGS(gro->gsobjno, gro->trgroupobjno); - gl2ps->xreflist[gro->trgroupobjno] = offs; - offs += gl2psPrintPDFShaderMask(gro->trgroupobjno, gro->maskshno); - gl2ps->xreflist[gro->maskshobjno] = offs; - offs += gl2psPrintPDFShader(gro->maskshobjno, triangles, size, 8); - } - gl2psFree(triangles); - break; - case GL2PS_PIXMAP: - gl2ps->xreflist[gro->imobjno] = offs; - offs += gl2psPrintPDFPixmap(gro->imobjno, gro->imobjno+1, p->data.image, 0); - if(p->data.image->format == GL_RGBA){ - gl2ps->xreflist[gro->imobjno+1] = offs; - offs += gl2psPrintPDFPixmap(gro->imobjno+1, -1, p->data.image, 8); - } - break; - case GL2PS_TEXT: - gl2ps->xreflist[gro->fontobjno] = offs; - offs += gl2psPrintPDFText(gro->fontobjno,p->data.text,gro->fontno); - break; - case GL2PS_SPECIAL : - /* alignment contains the format for which the special output text - is intended */ - if(p->data.text->alignment == GL2PS_PDF) - offs += fprintf(gl2ps->stream, "%s\n", p->data.text->str); - break; - default: - break; - } - } - return offs; -} - -/* All variable data has been written at this point and all required - functioninality has been gathered, so we can write now file footer - with cross reference table and trailer */ - -static void gl2psPrintPDFFooter(void) -{ - int i, offs; - - gl2psPDFgroupListInit(); - gl2psPDFgroupListWriteMainStream(); - - offs = gl2ps->xreflist[5] + gl2ps->streamlength; - offs += gl2psClosePDFDataStream(); - gl2ps->xreflist[5] = offs; - - offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength); - gl2ps->xreflist[6] = offs; - gl2ps->streamlength = 0; - - offs += gl2psPrintPDFOpenPage(); - offs += gl2psPDFgroupListWriteVariableResources(); - gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist, - sizeof(int) * (gl2ps->objects_stack + 1)); - gl2ps->xreflist[7] = offs; - - offs += gl2psPrintPDFGSObject(); - gl2ps->xreflist[8] = offs; - - gl2ps->xreflist[gl2ps->objects_stack] = - gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]); - - /* Start cross reference table. The file has to been opened in - binary mode to preserve the 20 digit string length! */ - fprintf(gl2ps->stream, - "xref\n" - "0 %d\n" - "%010d 65535 f \n", gl2ps->objects_stack, 0); - - for(i = 1; i < gl2ps->objects_stack; ++i) - fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]); - - fprintf(gl2ps->stream, - "trailer\n" - "<<\n" - "/Size %d\n" - "/Info 1 0 R\n" - "/Root 2 0 R\n" - ">>\n" - "startxref\n%d\n" - "%%%%EOF\n", - gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]); - - /* Free auxiliary lists and arrays */ - gl2psFree(gl2ps->xreflist); - gl2psListAction(gl2ps->pdfprimlist, gl2psFreePrimitive); - gl2psListDelete(gl2ps->pdfprimlist); - gl2psPDFgroupListDelete(); - -#if defined(GL2PS_HAVE_ZLIB) - if(gl2ps->options & GL2PS_COMPRESS){ - gl2psFreeCompress(); - gl2psFree(gl2ps->compress); - gl2ps->compress = NULL; - } -#endif -} - -/* PDF begin viewport */ - -static void gl2psPrintPDFBeginViewport(GLint viewport[4]) -{ - int offs = 0; - GLint index; - GLfloat rgba[4]; - int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; - - glRenderMode(GL_FEEDBACK); - - if(gl2ps->header){ - gl2psPrintPDFHeader(); - gl2ps->header = GL_FALSE; - } - - offs += gl2psPrintf("q\n"); - - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ - glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); - } - else{ - glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); - rgba[0] = gl2ps->colormap[index][0]; - rgba[1] = gl2ps->colormap[index][1]; - rgba[2] = gl2ps->colormap[index][2]; - rgba[3] = 1.0F; - } - offs += gl2psPrintPDFFillColor(rgba); - offs += gl2psPrintf("%d %d %d %d re\n" - "W\n" - "f\n", - x, y, w, h); - } - else{ - offs += gl2psPrintf("%d %d %d %d re\n" - "W\n" - "n\n", - x, y, w, h); - } - - gl2ps->streamlength += offs; -} - -static GLint gl2psPrintPDFEndViewport(void) -{ - GLint res; - - res = gl2psPrintPrimitives(); - gl2ps->streamlength += gl2psPrintf("Q\n"); - return res; -} - -static void gl2psPrintPDFFinalPrimitive(void) -{ -} - -/* definition of the PDF backend */ - -static GL2PSbackend gl2psPDF = { - gl2psPrintPDFHeader, - gl2psPrintPDFFooter, - gl2psPrintPDFBeginViewport, - gl2psPrintPDFEndViewport, - gl2psPrintPDFPrimitive, - gl2psPrintPDFFinalPrimitive, - "pdf", - "Portable Document Format" -}; - -/********************************************************************* - * - * SVG routines - * - *********************************************************************/ - -static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts, - GL2PSxyz *xyz, GL2PSrgba *rgba) -{ - int i, j; - - for(i = 0; i < n; i++){ - xyz[i][0] = verts[i].xyz[0]; - xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1]; - xyz[i][2] = 0.0F; - for(j = 0; j < 4; j++) - rgba[i][j] = verts[i].rgba[j]; - } -} - -static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32]) -{ - int r = (int)(255. * rgba[0]); - int g = (int)(255. * rgba[1]); - int b = (int)(255. * rgba[2]); - int rc = (r < 0) ? 0 : (r > 255) ? 255 : r; - int gc = (g < 0) ? 0 : (g > 255) ? 255 : g; - int bc = (b < 0) ? 0 : (b > 255) ? 255 : b; - sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc); -} - -static void gl2psPrintSVGHeader(void) -{ - int x, y, width, height; - char col[32]; - time_t now; - - time(&now); - - if (gl2ps->options & GL2PS_LANDSCAPE){ - x = (int)gl2ps->viewport[1]; - y = (int)gl2ps->viewport[0]; - width = (int)gl2ps->viewport[3]; - height = (int)gl2ps->viewport[2]; - } - else{ - x = (int)gl2ps->viewport[0]; - y = (int)gl2ps->viewport[1]; - width = (int)gl2ps->viewport[2]; - height = (int)gl2ps->viewport[3]; - } - - /* Compressed SVG files (.svgz) are simply gzipped SVG files */ - gl2psPrintGzipHeader(); - - gl2psPrintf("\n"); - gl2psPrintf("\n", - width, height, x, y, width, height); - gl2psPrintf("%s\n", gl2ps->title); - gl2psPrintf("\n"); - gl2psPrintf("Creator: GL2PS %d.%d.%d%s, %s\n" - "For: %s\n" - "CreationDate: %s", - GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION, - GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, gl2ps->producer, ctime(&now)); - gl2psPrintf("\n"); - gl2psPrintf("\n"); - gl2psPrintf("\n"); - - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - gl2psSVGGetColorString(gl2ps->bgcolor, col); - gl2psPrintf("\n", col, - (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], - (int)gl2ps->viewport[2], (int)gl2ps->viewport[1], - (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], - (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]); - } - - /* group all the primitives and disable antialiasing */ - gl2psPrintf("\n"); -} - -static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3]) -{ - int i; - GL2PSxyz xyz2[3]; - GL2PSrgba rgba2[3]; - char col[32]; - - /* Apparently there is no easy way to do Gouraud shading in SVG - without explicitly pre-defining gradients, so for now we just do - recursive subdivision */ - - if(gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){ - gl2psSVGGetColorString(rgba[0], col); - gl2psPrintf("\n", xyz[0][0], xyz[0][1], - xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]); - } - else{ - /* subdivide into 4 subtriangles */ - for(i = 0; i < 3; i++){ - xyz2[0][i] = xyz[0][i]; - xyz2[1][i] = 0.5 * (xyz[0][i] + xyz[1][i]); - xyz2[2][i] = 0.5 * (xyz[0][i] + xyz[2][i]); - } - for(i = 0; i < 4; i++){ - rgba2[0][i] = rgba[0][i]; - rgba2[1][i] = 0.5 * (rgba[0][i] + rgba[1][i]); - rgba2[2][i] = 0.5 * (rgba[0][i] + rgba[2][i]); - } - gl2psPrintSVGSmoothTriangle(xyz2, rgba2); - for(i = 0; i < 3; i++){ - xyz2[0][i] = 0.5 * (xyz[0][i] + xyz[1][i]); - xyz2[1][i] = xyz[1][i]; - xyz2[2][i] = 0.5 * (xyz[1][i] + xyz[2][i]); - } - for(i = 0; i < 4; i++){ - rgba2[0][i] = 0.5 * (rgba[0][i] + rgba[1][i]); - rgba2[1][i] = rgba[1][i]; - rgba2[2][i] = 0.5 * (rgba[1][i] + rgba[2][i]); - } - gl2psPrintSVGSmoothTriangle(xyz2, rgba2); - for(i = 0; i < 3; i++){ - xyz2[0][i] = 0.5 * (xyz[0][i] + xyz[2][i]); - xyz2[1][i] = xyz[2][i]; - xyz2[2][i] = 0.5 * (xyz[1][i] + xyz[2][i]); - } - for(i = 0; i < 4; i++){ - rgba2[0][i] = 0.5 * (rgba[0][i] + rgba[2][i]); - rgba2[1][i] = rgba[2][i]; - rgba2[2][i] = 0.5 * (rgba[1][i] + rgba[2][i]); - } - gl2psPrintSVGSmoothTriangle(xyz2, rgba2); - for(i = 0; i < 3; i++){ - xyz2[0][i] = 0.5 * (xyz[0][i] + xyz[1][i]); - xyz2[1][i] = 0.5 * (xyz[1][i] + xyz[2][i]); - xyz2[2][i] = 0.5 * (xyz[0][i] + xyz[2][i]); - } - for(i = 0; i < 4; i++){ - rgba2[0][i] = 0.5 * (rgba[0][i] + rgba[1][i]); - rgba2[1][i] = 0.5 * (rgba[1][i] + rgba[2][i]); - rgba2[2][i] = 0.5 * (rgba[0][i] + rgba[2][i]); - } - gl2psPrintSVGSmoothTriangle(xyz2, rgba2); - } -} - -static void gl2psPrintSVGDash(GLushort pattern, GLint factor) -{ - int i, n, array[10]; - - if(!pattern || !factor) return; /* solid line */ - - gl2psParseStipplePattern(pattern, factor, &n, array); - gl2psPrintf("stroke-dasharray=\""); - for(i = 0; i < n; i++){ - if(i) gl2psPrintf(","); - gl2psPrintf("%d", array[i]); - } - gl2psPrintf("\" "); -} - -static void gl2psEndSVGLine(void) -{ - int i; - if(gl2ps->lastvertex.rgba[0] >= 0.){ - gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0], - gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]); - for(i = 0; i < 3; i++) - gl2ps->lastvertex.xyz[i] = -1.; - for(i = 0; i < 4; i++) - gl2ps->lastvertex.rgba[i] = -1.; - } -} - -static void gl2psPrintSVGPixmap(GLfloat /*x*/, GLfloat /*y*/, GL2PSimage * /*pixmap*/) -{ -#if defined(GL2PS_HAVE_LIBPNG) - GL2PSlist *png; - unsigned char c; - int i; - - /* The only image types supported by the SVG standard are JPEG, PNG - and SVG. Here we choose PNG, and since we want to embed the image - directly in the SVG stream (and not link to an external image - file), we need to encode the pixmap into PNG in memory, then - encode it into base64. */ - - png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000, - sizeof(unsigned char)); - gl2psConvertPixmapToPNG(pixmap, png); - gl2psListEncodeBase64(png); - gl2psPrintf("height, pixmap->width, pixmap->height); - gl2psPrintf("xlink:href=\"data:image/png;base64,"); - for(i = 0; i < gl2psListNbr(png); i++){ - gl2psListRead(png, i, &c); - gl2psPrintf("%c", c); - } - gl2psPrintf("\"/>\n"); - gl2psListDelete(png); -#else - gl2psMsg(GL2PS_WARNING, "GL2PS has to be compiled with PNG support in " - "order to embed images in SVG streams"); -#endif -} - -static void gl2psPrintSVGPrimitive(void *data) -{ - GL2PSprimitive *prim; - GL2PSxyz xyz[4]; - GL2PSrgba rgba[4]; - char col[32]; - int newline; - - prim = *(GL2PSprimitive**)data; - - if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return; - - /* We try to draw connected lines as a single path to get nice line - joins and correct stippling. So if the primitive to print is not - a line we must first finish the current line (if any): */ - if(prim->type != GL2PS_LINE) gl2psEndSVGLine(); - - gl2psSVGGetCoordsAndColors(prim->numverts, prim->verts, xyz, rgba); - - switch(prim->type){ - case GL2PS_POINT : - gl2psSVGGetColorString(rgba[0], col); - gl2psPrintf("\n", - xyz[0][0], xyz[0][1], 0.5 * prim->width); - break; - case GL2PS_LINE : - if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) || - !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) || - gl2ps->lastlinewidth != prim->width || - gl2ps->lastpattern != prim->pattern || - gl2ps->lastfactor != prim->factor){ - /* End the current line if the new segment does not start where - the last one ended, or if the color, the width or the - stippling have changed (we will need to use multi-point - gradients for smooth-shaded lines) */ - gl2psEndSVGLine(); - newline = 1; - } - else{ - newline = 0; - } - gl2ps->lastvertex = prim->verts[1]; - gl2psSetLastColor(prim->verts[0].rgba); - gl2ps->lastlinewidth = prim->width; - gl2ps->lastpattern = prim->pattern; - gl2ps->lastfactor = prim->factor; - if(newline){ - gl2psSVGGetColorString(rgba[0], col); - gl2psPrintf("width); - if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]); - gl2psPrintSVGDash(prim->pattern, prim->factor); - gl2psPrintf("points=\"%g,%g ", xyz[0][0], xyz[0][1]); - } - else{ - gl2psPrintf("%g,%g ", xyz[0][0], xyz[0][1]); - } - break; - case GL2PS_TRIANGLE : - gl2psPrintSVGSmoothTriangle(xyz, rgba); - break; - case GL2PS_QUADRANGLE : - gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print"); - break; - case GL2PS_PIXMAP : - gl2psPrintSVGPixmap(xyz[0][0], xyz[0][1], prim->data.image); - break; - case GL2PS_TEXT : - gl2psSVGGetColorString(prim->verts[0].rgba, col); - gl2psPrintf("data.text->fontsize); - if(!strcmp(prim->data.text->fontname, "Times-Roman")) - gl2psPrintf("font-family=\"Times\">"); - else if(!strcmp(prim->data.text->fontname, "Times-Bold")) - gl2psPrintf("font-family=\"Times\" font-weight=\"bold\">"); - else if(!strcmp(prim->data.text->fontname, "Times-Italic")) - gl2psPrintf("font-family=\"Times\" font-style=\"italic\">"); - else if(!strcmp(prim->data.text->fontname, "Times-BoldItalic")) - gl2psPrintf("font-family=\"Times\" font-style=\"italic\" font-weight=\"bold\">"); - else if(!strcmp(prim->data.text->fontname, "Helvetica-Bold")) - gl2psPrintf("font-family=\"Helvetica\" font-weight=\"bold\">"); - else if(!strcmp(prim->data.text->fontname, "Helvetica-Oblique")) - gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\">"); - else if(!strcmp(prim->data.text->fontname, "Helvetica-BoldOblique")) - gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\" font-weight=\"bold\">"); - else if(!strcmp(prim->data.text->fontname, "Courier-Bold")) - gl2psPrintf("font-family=\"Courier\" font-weight=\"bold\">"); - else if(!strcmp(prim->data.text->fontname, "Courier-Oblique")) - gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\">"); - else if(!strcmp(prim->data.text->fontname, "Courier-BoldOblique")) - gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\" font-weight=\"bold\">"); - else - gl2psPrintf("font-family=\"%s\">", prim->data.text->fontname); - gl2psPrintf("%s\n", prim->data.text->str); - break; - case GL2PS_SPECIAL : - /* alignment contains the format for which the special output text - is intended */ - if(prim->data.text->alignment == GL2PS_SVG) - gl2psPrintf("%s\n", prim->data.text->str); - break; - default : - break; - } -} - -static void gl2psPrintSVGFooter(void) -{ - gl2psPrintf("\n"); - gl2psPrintf("\n"); - - gl2psPrintGzipFooter(); -} - -static void gl2psPrintSVGBeginViewport(GLint viewport[4]) -{ - GLint index; - char col[32]; - GLfloat rgba[4]; - int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; - - glRenderMode(GL_FEEDBACK); - - if(gl2ps->header){ - gl2psPrintSVGHeader(); - gl2ps->header = GL_FALSE; - } - - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ - glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); - } - else{ - glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); - rgba[0] = gl2ps->colormap[index][0]; - rgba[1] = gl2ps->colormap[index][1]; - rgba[2] = gl2ps->colormap[index][2]; - rgba[3] = 1.0F; - } - gl2psSVGGetColorString(rgba, col); - gl2psPrintf("\n", col, - x, gl2ps->viewport[3] - y, - x + w, gl2ps->viewport[3] - y, - x + w, gl2ps->viewport[3] - (y + h), - x, gl2ps->viewport[3] - (y + h)); - } - - gl2psPrintf("\n", x, y, w, h); - gl2psPrintf(" \n", - x, gl2ps->viewport[3] - y, - x + w, gl2ps->viewport[3] - y, - x + w, gl2ps->viewport[3] - (y + h), - x, gl2ps->viewport[3] - (y + h)); - gl2psPrintf("\n"); - gl2psPrintf("\n", x, y, w, h); -} - -static GLint gl2psPrintSVGEndViewport(void) -{ - GLint res; - - res = gl2psPrintPrimitives(); - gl2psPrintf("\n"); - return res; -} - -static void gl2psPrintSVGFinalPrimitive(void) -{ - /* End any remaining line, if any */ - gl2psEndSVGLine(); -} - -/* definition of the SVG backend */ - -static GL2PSbackend gl2psSVG = { - gl2psPrintSVGHeader, - gl2psPrintSVGFooter, - gl2psPrintSVGBeginViewport, - gl2psPrintSVGEndViewport, - gl2psPrintSVGPrimitive, - gl2psPrintSVGFinalPrimitive, - "svg", - "Scalable Vector Graphics" -}; - -/********************************************************************* - * - * PGF routines - * - *********************************************************************/ - -static void gl2psPrintPGFColor(GL2PSrgba rgba) -{ - if(!gl2psSameColor(gl2ps->lastrgba, rgba)){ - gl2psSetLastColor(rgba); - fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]); - } -} - -static void gl2psPrintPGFHeader(void) -{ - time_t now; - - time(&now); - - fprintf(gl2ps->stream, - "%% Title: %s\n" - "%% Creator: GL2PS %d.%d.%d%s, %s\n" - "%% For: %s\n" - "%% CreationDate: %s", - gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, - GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, - gl2ps->producer, ctime(&now)); - - fprintf(gl2ps->stream, "\\begin{pgfpicture}\n"); - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - gl2psPrintPGFColor(gl2ps->bgcolor); - fprintf(gl2ps->stream, - "\\pgfpathrectanglecorners{" - "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n" - "\\pgfusepath{fill}\n", - (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], - (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); - } -} - -static void gl2psPrintPGFDash(GLushort pattern, GLint factor) -{ - int i, n, array[10]; - - if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor) - return; - - gl2ps->lastpattern = pattern; - gl2ps->lastfactor = factor; - - if(!pattern || !factor){ - /* solid line */ - fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n"); - } - else{ - gl2psParseStipplePattern(pattern, factor, &n, array); - fprintf(gl2ps->stream, "\\pgfsetdash{"); - for(i = 0; i < n; i++) fprintf(gl2ps->stream, "{%dpt}", array[i]); - fprintf(gl2ps->stream, "}{0pt}\n"); - } -} - -static const char *gl2psPGFTextAlignment(int align) -{ - switch(align){ - case GL2PS_TEXT_C : return "center"; - case GL2PS_TEXT_CL : return "west"; - case GL2PS_TEXT_CR : return "east"; - case GL2PS_TEXT_B : return "south"; - case GL2PS_TEXT_BR : return "south east"; - case GL2PS_TEXT_T : return "north"; - case GL2PS_TEXT_TL : return "north west"; - case GL2PS_TEXT_TR : return "north east"; - case GL2PS_TEXT_BL : - default : return "south west"; - } -} - -static void gl2psPrintPGFPrimitive(void *data) -{ - GL2PSprimitive *prim; - - prim = *(GL2PSprimitive**)data; - - switch(prim->type){ - case GL2PS_POINT : - /* Points in openGL are rectangular */ - gl2psPrintPGFColor(prim->verts[0].rgba); - fprintf(gl2ps->stream, - "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}" - "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n", - prim->verts[0].xyz[0]-0.5*prim->width, - prim->verts[0].xyz[1]-0.5*prim->width, - prim->width,prim->width); - break; - case GL2PS_LINE : - gl2psPrintPGFColor(prim->verts[0].rgba); - if(gl2ps->lastlinewidth != prim->width){ - gl2ps->lastlinewidth = prim->width; - fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth); - } - gl2psPrintPGFDash(prim->pattern, prim->factor); - fprintf(gl2ps->stream, - "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n" - "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n" - "\\pgfusepath{stroke}\n", - prim->verts[1].xyz[0], prim->verts[1].xyz[1], - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - break; - case GL2PS_TRIANGLE : - if(gl2ps->lastlinewidth != 0){ - gl2ps->lastlinewidth = 0; - fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n"); - } - gl2psPrintPGFColor(prim->verts[0].rgba); - fprintf(gl2ps->stream, - "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n" - "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n" - "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n" - "\\pgfpathclose\n" - "\\pgfusepath{fill,stroke}\n", - prim->verts[2].xyz[0], prim->verts[2].xyz[1], - prim->verts[1].xyz[0], prim->verts[1].xyz[1], - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - break; - case GL2PS_TEXT : - fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n", - prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - - if(prim->data.text->angle) - fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle); - - fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont", - gl2psPGFTextAlignment(prim->data.text->alignment), - prim->data.text->fontsize); - - fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}", - prim->verts[0].rgba[0], prim->verts[0].rgba[1], - prim->verts[0].rgba[2], prim->data.text->str); - - fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}}\n"); - break; - case GL2PS_SPECIAL : - /* alignment contains the format for which the special output text - is intended */ - if (prim->data.text->alignment == GL2PS_PGF) - fprintf(gl2ps->stream, "%s\n", prim->data.text->str); - break; - default : - break; - } -} - -static void gl2psPrintPGFFooter(void) -{ - fprintf(gl2ps->stream, "\\end{pgfpicture}\n"); -} - -static void gl2psPrintPGFBeginViewport(GLint viewport[4]) -{ - GLint index; - GLfloat rgba[4]; - int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; - - glRenderMode(GL_FEEDBACK); - - if(gl2ps->header){ - gl2psPrintPGFHeader(); - gl2ps->header = GL_FALSE; - } - - fprintf(gl2ps->stream, "\\begin{pgfscope}\n"); - if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ - if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ - glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); - } - else{ - glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); - rgba[0] = gl2ps->colormap[index][0]; - rgba[1] = gl2ps->colormap[index][1]; - rgba[2] = gl2ps->colormap[index][2]; - rgba[3] = 1.0F; - } - gl2psPrintPGFColor(rgba); - fprintf(gl2ps->stream, - "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}" - "{\\pgfpoint{%dpt}{%dpt}}\n" - "\\pgfusepath{fill}\n", - x, y, w, h); - } - - fprintf(gl2ps->stream, - "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}" - "{\\pgfpoint{%dpt}{%dpt}}\n" - "\\pgfusepath{clip}\n", - x, y, w, h); -} - -static GLint gl2psPrintPGFEndViewport(void) -{ - GLint res; - res = gl2psPrintPrimitives(); - fprintf(gl2ps->stream, "\\end{pgfscope}\n"); - return res; -} - -static void gl2psPrintPGFFinalPrimitive(void) -{ -} - -/* definition of the PGF backend */ - -static GL2PSbackend gl2psPGF = { - gl2psPrintPGFHeader, - gl2psPrintPGFFooter, - gl2psPrintPGFBeginViewport, - gl2psPrintPGFEndViewport, - gl2psPrintPGFPrimitive, - gl2psPrintPGFFinalPrimitive, - "tex", - "PGF Latex Graphics" -}; - -/********************************************************************* - * - * General primitive printing routine - * - *********************************************************************/ - -/* Warning: the ordering of the backends must match the format - #defines in gl2ps.h */ - -static GL2PSbackend *gl2psbackends[] = { - &gl2psPS, /* 0 */ - &gl2psEPS, /* 1 */ - &gl2psTEX, /* 2 */ - &gl2psPDF, /* 3 */ - &gl2psSVG, /* 4 */ - &gl2psPGF /* 5 */ -}; - -static void gl2psComputeTightBoundingBox(void *data) -{ - GL2PSprimitive *prim; - int i; - - prim = *(GL2PSprimitive**)data; - - for(i = 0; i < prim->numverts; i++){ - if(prim->verts[i].xyz[0] < gl2ps->viewport[0]) - gl2ps->viewport[0] = (GLint)prim->verts[i].xyz[0]; - if(prim->verts[i].xyz[0] > gl2ps->viewport[2]) - gl2ps->viewport[2] = (GLint)(prim->verts[i].xyz[0] + 0.5F); - if(prim->verts[i].xyz[1] < gl2ps->viewport[1]) - gl2ps->viewport[1] = (GLint)prim->verts[i].xyz[1]; - if(prim->verts[i].xyz[1] > gl2ps->viewport[3]) - gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F); - } -} - -static GLint gl2psPrintPrimitives(void) -{ - GL2PSbsptree *root; - GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE}; - GLint used; - - used = glRenderMode(GL_RENDER); - - if(used < 0){ - gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow"); - return GL2PS_OVERFLOW; - } - - if(used > 0) - gl2psParseFeedbackBuffer(used); - - gl2psRescaleAndOffset(); - - if(gl2ps->header){ - if(gl2psListNbr(gl2ps->primitives) && - (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){ - gl2ps->viewport[0] = gl2ps->viewport[1] = 100000; - gl2ps->viewport[2] = gl2ps->viewport[3] = -100000; - gl2psListAction(gl2ps->primitives, gl2psComputeTightBoundingBox); - } - (gl2psbackends[gl2ps->format]->printHeader)(); - gl2ps->header = GL_FALSE; - } - - if(!gl2psListNbr(gl2ps->primitives)){ - /* empty feedback buffer and/or nothing else to print */ - return GL2PS_NO_FEEDBACK; - } - - switch(gl2ps->sort){ - case GL2PS_NO_SORT : - gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive); - gl2psListAction(gl2ps->primitives, gl2psFreePrimitive); - /* reset the primitive list, waiting for the next viewport */ - gl2psListReset(gl2ps->primitives); - break; - case GL2PS_SIMPLE_SORT : - gl2psListSort(gl2ps->primitives, gl2psCompareDepth); - if(gl2ps->options & GL2PS_OCCLUSION_CULL){ - gl2psListActionInverse(gl2ps->primitives, gl2psAddInImageTree); - gl2psFreeBspImageTree(&gl2ps->imagetree); - } - gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive); - gl2psListAction(gl2ps->primitives, gl2psFreePrimitive); - /* reset the primitive list, waiting for the next viewport */ - gl2psListReset(gl2ps->primitives); - break; - case GL2PS_BSP_SORT : - root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); - gl2psBuildBspTree(root, gl2ps->primitives); - if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root); - if(gl2ps->options & GL2PS_OCCLUSION_CULL){ - gl2psTraverseBspTree(root, eye, -GL2PS_EPSILON, gl2psLess, - gl2psAddInImageTree, 1); - gl2psFreeBspImageTree(&gl2ps->imagetree); - } - gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater, - gl2psbackends[gl2ps->format]->printPrimitive, 0); - gl2psFreeBspTree(&root); - /* reallocate the primitive list (it's been deleted by - gl2psBuildBspTree) in case there is another viewport */ - gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); - break; - } - gl2psbackends[gl2ps->format]->printFinalPrimitive(); - - return GL2PS_SUCCESS; -} - -/********************************************************************* - * - * Public routines - * - *********************************************************************/ - -GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, - GLint viewport[4], GLint format, GLint sort, - GLint options, GLint colormode, - GLint colorsize, GL2PSrgba *colormap, - GLint nr, GLint ng, GLint nb, GLint buffersize, - FILE *stream, const char *filename) -{ - GLint index; - int i; - - if(gl2ps){ - gl2psMsg(GL2PS_ERROR, "gl2psBeginPage called in wrong program state"); - return GL2PS_ERROR; - } - - gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext)); - - if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0]))){ - gl2ps->format = format; - } - else { - gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", format); - gl2psFree(gl2ps); - gl2ps = NULL; - return GL2PS_ERROR; - } - - switch(sort){ - case GL2PS_NO_SORT : - case GL2PS_SIMPLE_SORT : - case GL2PS_BSP_SORT : - gl2ps->sort = sort; - break; - default : - gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", sort); - gl2psFree(gl2ps); - gl2ps = NULL; - return GL2PS_ERROR; - } - - if(stream){ - gl2ps->stream = stream; - } - else{ - gl2psMsg(GL2PS_ERROR, "Bad file pointer"); - gl2psFree(gl2ps); - gl2ps = NULL; - return GL2PS_ERROR; - } - - gl2ps->header = GL_TRUE; - gl2ps->maxbestroot = 10; - gl2ps->options = options; - gl2ps->compress = NULL; - gl2ps->imagemap_head = NULL; - gl2ps->imagemap_tail = NULL; - - if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){ - glGetIntegerv(GL_VIEWPORT, gl2ps->viewport); - } - else{ - for(i = 0; i < 4; i++){ - gl2ps->viewport[i] = viewport[i]; - } - } - - if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){ - gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)", - gl2ps->viewport[0], gl2ps->viewport[1], - gl2ps->viewport[2], gl2ps->viewport[3]); - gl2psFree(gl2ps); - gl2ps = NULL; - return GL2PS_ERROR; - } - - gl2ps->threshold[0] = nr ? 1.0F / (GLfloat)nr : 0.064F; - gl2ps->threshold[1] = ng ? 1.0F / (GLfloat)ng : 0.034F; - gl2ps->threshold[2] = nb ? 1.0F / (GLfloat)nb : 0.100F; - gl2ps->colormode = colormode; - gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048; - for(i = 0; i < 3; i++){ - gl2ps->lastvertex.xyz[i] = -1.0F; - } - for(i = 0; i < 4; i++){ - gl2ps->lastvertex.rgba[i] = -1.0F; - gl2ps->lastrgba[i] = -1.0F; - } - gl2ps->lastlinewidth = -1.0F; - gl2ps->lastpattern = 0; - gl2ps->lastfactor = 0; - gl2ps->imagetree = NULL; - gl2ps->primitivetoadd = NULL; - gl2ps->zerosurfacearea = GL_FALSE; - gl2ps->pdfprimlist = NULL; - gl2ps->pdfgrouplist = NULL; - gl2ps->xreflist = NULL; - - /* get default blending mode from current OpenGL state (enabled by - default for SVG) */ - gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND); - glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]); - glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]); - - if(gl2ps->colormode == GL_RGBA){ - gl2ps->colorsize = 0; - gl2ps->colormap = NULL; - glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor); - } - else if(gl2ps->colormode == GL_COLOR_INDEX){ - if(!colorsize || !colormap){ - gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering"); - gl2psFree(gl2ps); - gl2ps = NULL; - return GL2PS_ERROR; - } - gl2ps->colorsize = colorsize; - gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba)); - memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba)); - glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); - gl2ps->bgcolor[0] = gl2ps->colormap[index][0]; - gl2ps->bgcolor[1] = gl2ps->colormap[index][1]; - gl2ps->bgcolor[2] = gl2ps->colormap[index][2]; - gl2ps->bgcolor[3] = 1.0F; - } - else{ - gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage"); - gl2psFree(gl2ps); - gl2ps = NULL; - return GL2PS_ERROR; - } - - if(!title){ - gl2ps->title = (char*)gl2psMalloc(sizeof(char)); - gl2ps->title[0] = '\0'; - } - else{ - gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char)); - strcpy(gl2ps->title, title); - } - - if(!producer){ - gl2ps->producer = (char*)gl2psMalloc(sizeof(char)); - gl2ps->producer[0] = '\0'; - } - else{ - gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char)); - strcpy(gl2ps->producer, producer); - } - - if(!filename){ - gl2ps->filename = (char*)gl2psMalloc(sizeof(char)); - gl2ps->filename[0] = '\0'; - } - else{ - gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char)); - strcpy(gl2ps->filename, filename); - } - - gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); - gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*)); - gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat)); - glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback); - glRenderMode(GL_FEEDBACK); - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psEndPage(void) -{ - GLint res; - - if(!gl2ps) return GL2PS_UNINITIALIZED; - - res = gl2psPrintPrimitives(); - - if(res != GL2PS_OVERFLOW) - (gl2psbackends[gl2ps->format]->printFooter)(); - - fflush(gl2ps->stream); - - gl2psListDelete(gl2ps->primitives); - gl2psListDelete(gl2ps->auxprimitives); - gl2psFreeImagemap(gl2ps->imagemap_head); - gl2psFree(gl2ps->colormap); - gl2psFree(gl2ps->title); - gl2psFree(gl2ps->producer); - gl2psFree(gl2ps->filename); - gl2psFree(gl2ps->feedback); - gl2psFree(gl2ps); - gl2ps = NULL; - - return res; -} - -GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]) -{ - if(!gl2ps) return GL2PS_UNINITIALIZED; - - (gl2psbackends[gl2ps->format]->beginViewport)(viewport); - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psEndViewport(void) -{ - GLint res; - - if(!gl2ps) return GL2PS_UNINITIALIZED; - - res = (gl2psbackends[gl2ps->format]->endViewport)(); - - /* reset last used colors, line widths */ - gl2ps->lastlinewidth = -1.0F; - - return res; -} - -GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, - GLshort fontsize, GLint alignment, GLfloat angle) -{ - return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle); -} - -GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize) -{ - return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F); -} - -GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str) -{ - return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F); -} - -GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, - GLint xorig, GLint yorig, - GLenum format, GLenum type, - const void *pixels) -{ - int size, i; - GLfloat pos[4], *piv; - GL2PSprimitive *prim; - GLboolean valid; - - if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED; - - if((width <= 0) || (height <= 0)) return GL2PS_ERROR; - - if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS; - - if((format != GL_RGB && format != GL_RGBA) || type != GL_FLOAT){ - gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for " - "GL_RGB/GL_RGBA, GL_FLOAT pixels"); - return GL2PS_ERROR; - } - - glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid); - if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */ - - glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); - - prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); - prim->type = GL2PS_PIXMAP; - prim->boundary = 0; - prim->numverts = 1; - prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex)); - prim->verts[0].xyz[0] = pos[0] + xorig; - prim->verts[0].xyz[1] = pos[1] + yorig; - prim->verts[0].xyz[2] = pos[2]; - prim->culled = 0; - prim->offset = 0; - prim->pattern = 0; - prim->factor = 0; - prim->width = 1; - glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); - prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); - prim->data.image->width = width; - prim->data.image->height = height; - prim->data.image->format = format; - prim->data.image->type = type; - - switch(format){ - case GL_RGBA: - if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){ - /* special case: blending turned off */ - prim->data.image->format = GL_RGB; - size = height * width * 3; - prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat)); - piv = (GLfloat*)pixels; - for(i = 0; i < size; ++i, ++piv){ - prim->data.image->pixels[i] = *piv; - if(!((i+1)%3)) - ++piv; - } - } - else{ - size = height * width * 4; - prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat)); - memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat)); - } - break; - case GL_RGB: - default: - size = height * width * 3; - prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat)); - memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat)); - break; - } - - gl2psListAdd(gl2ps->auxprimitives, &prim); - glPassThrough(GL2PS_DRAW_PIXELS_TOKEN); - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height, - const GLfloat position[3], - const unsigned char *imagemap){ - int size, i; - int sizeoffloat = sizeof(GLfloat); - - if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED; - - if((width <= 0) || (height <= 0)) return GL2PS_ERROR; - - size = height + height * ((width - 1) / 8); - glPassThrough(GL2PS_IMAGEMAP_TOKEN); - glBegin(GL_POINTS); - glVertex3f(position[0], position[1],position[2]); - glEnd(); - glPassThrough((GLfloat)width); - glPassThrough((GLfloat)height); - for(i = 0; i < size; i += sizeoffloat){ - float *value = (float*)imagemap; - glPassThrough(*value); - imagemap += sizeoffloat; - } - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psEnable(GLint mode) -{ - GLint tmp; - - if(!gl2ps) return GL2PS_UNINITIALIZED; - - switch(mode){ - case GL2PS_POLYGON_OFFSET_FILL : - glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN); - glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]); - glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]); - break; - case GL2PS_POLYGON_BOUNDARY : - glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN); - break; - case GL2PS_LINE_STIPPLE : - glPassThrough(GL2PS_BEGIN_STIPPLE_TOKEN); - glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp); - glPassThrough((GLfloat)tmp); - glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp); - glPassThrough((GLfloat)tmp); - break; - case GL2PS_BLEND : - glPassThrough(GL2PS_BEGIN_BLEND_TOKEN); - break; - default : - gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode); - return GL2PS_WARNING; - } - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psDisable(GLint mode) -{ - if(!gl2ps) return GL2PS_UNINITIALIZED; - - switch(mode){ - case GL2PS_POLYGON_OFFSET_FILL : - glPassThrough(GL2PS_END_OFFSET_TOKEN); - break; - case GL2PS_POLYGON_BOUNDARY : - glPassThrough(GL2PS_END_BOUNDARY_TOKEN); - break; - case GL2PS_LINE_STIPPLE : - glPassThrough(GL2PS_END_STIPPLE_TOKEN); - break; - case GL2PS_BLEND : - glPassThrough(GL2PS_END_BLEND_TOKEN); - break; - default : - gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode); - return GL2PS_WARNING; - } - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psPointSize(GLfloat value) -{ - if(!gl2ps) return GL2PS_UNINITIALIZED; - - glPassThrough(GL2PS_POINT_SIZE_TOKEN); - glPassThrough(value); - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psLineWidth(GLfloat value) -{ - if(!gl2ps) return GL2PS_UNINITIALIZED; - - glPassThrough(GL2PS_LINE_WIDTH_TOKEN); - glPassThrough(value); - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor) -{ - if(!gl2ps) return GL2PS_UNINITIALIZED; - - if(GL_FALSE == gl2psSupportedBlendMode(sfactor, dfactor)) - return GL2PS_WARNING; - - glPassThrough(GL2PS_SRC_BLEND_TOKEN); - glPassThrough((GLfloat)sfactor); - glPassThrough(GL2PS_DST_BLEND_TOKEN); - glPassThrough((GLfloat)dfactor); - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psSetOptions(GLint options) -{ - if(!gl2ps) return GL2PS_UNINITIALIZED; - - gl2ps->options = options; - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API GLint gl2psGetOptions(GLint *options) -{ - if(!gl2ps) { - *options = 0; - return GL2PS_UNINITIALIZED; - } - - *options = gl2ps->options; - - return GL2PS_SUCCESS; -} - -GL2PSDLL_API const char *gl2psGetFileExtension(GLint format) -{ - if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0]))) - return gl2psbackends[format]->file_extension; - else - return "Unknown format"; -} - -GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format) -{ - if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0]))) - return gl2psbackends[format]->description; - else - return "Unknown format"; -} diff --git a/graf3d/gl/src/gl2ps/gl2ps.h b/graf3d/gl/src/gl2ps/gl2ps.h deleted file mode 100644 index 54033a474490b..0000000000000 --- a/graf3d/gl/src/gl2ps/gl2ps.h +++ /dev/null @@ -1,183 +0,0 @@ -// @(#)root/gl:$Id$ -/* - * GL2PS, an OpenGL to PostScript Printing Library - * Copyright (C) 1999-2009 C. Geuzaine - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of either: - * - * a) the GNU Library General Public License as published by the Free - * Software Foundation, either version 2 of the License, or (at your - * option) any later version; or - * - * b) the GL2PS License as published by Christophe Geuzaine, either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either - * the GNU Library General Public License or the GL2PS License for - * more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library in the file named "COPYING.LGPL"; - * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, - * Cambridge, MA 02139, USA. - * - * You should have received a copy of the GL2PS License with this - * library in the file named "COPYING.GL2PS"; if not, I will be glad - * to provide one. - * - * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/. - * Please report all bugs and problems to . - */ - -#ifndef __GL2PS_H__ -#define __GL2PS_H__ - -#include -#include - -#ifdef WIN32 -#include "Windows4Root.h" -#endif - -#ifdef __APPLE__ -#include -#else -#include -#endif - -#define GL2PSDLL_API - -/* Support for compressed PostScript/PDF/SVG and for embedded PNG - images in SVG */ - -#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ) -# define GL2PS_HAVE_ZLIB -# if defined(HAVE_LIBPNG) || defined(HAVE_PNG) -# define GL2PS_HAVE_LIBPNG -# endif -#endif - -/* Version number */ - -#define GL2PS_MAJOR_VERSION 1 -#define GL2PS_MINOR_VERSION 3 -#define GL2PS_PATCH_VERSION 3 -#define GL2PS_EXTRA_VERSION "" - -#define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \ - 0.01 * GL2PS_MINOR_VERSION + \ - 0.0001 * GL2PS_PATCH_VERSION) - -#define GL2PS_COPYRIGHT "(C) 1999-2009 C. Geuzaine" - -/* Output file formats (the values and the ordering are important!) */ - -#define GL2PS_PS 0 -#define GL2PS_EPS 1 -#define GL2PS_TEX 2 -#define GL2PS_PDF 3 -#define GL2PS_SVG 4 -#define GL2PS_PGF 5 - -/* Sorting algorithms */ - -#define GL2PS_NO_SORT 1 -#define GL2PS_SIMPLE_SORT 2 -#define GL2PS_BSP_SORT 3 - -/* Message levels and error codes */ - -#define GL2PS_SUCCESS 0 -#define GL2PS_INFO 1 -#define GL2PS_WARNING 2 -#define GL2PS_ERROR 3 -#define GL2PS_NO_FEEDBACK 4 -#define GL2PS_OVERFLOW 5 -#define GL2PS_UNINITIALIZED 6 - -/* Options for gl2psBeginPage */ - -#define GL2PS_NONE 0 -#define GL2PS_DRAW_BACKGROUND (1<<0) -#define GL2PS_SIMPLE_LINE_OFFSET (1<<1) -#define GL2PS_SILENT (1<<2) -#define GL2PS_BEST_ROOT (1<<3) -#define GL2PS_OCCLUSION_CULL (1<<4) -#define GL2PS_NO_TEXT (1<<5) -#define GL2PS_LANDSCAPE (1<<6) -#define GL2PS_NO_PS3_SHADING (1<<7) -#define GL2PS_NO_PIXMAP (1<<8) -#define GL2PS_USE_CURRENT_VIEWPORT (1<<9) -#define GL2PS_COMPRESS (1<<10) -#define GL2PS_NO_BLENDING (1<<11) -#define GL2PS_TIGHT_BOUNDING_BOX (1<<12) - -/* Arguments for gl2psEnable/gl2psDisable */ - -#define GL2PS_POLYGON_OFFSET_FILL 1 -#define GL2PS_POLYGON_BOUNDARY 2 -#define GL2PS_LINE_STIPPLE 3 -#define GL2PS_BLEND 4 - -/* Text alignment (o=raster position; default mode is BL): - +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o - | o | o | | o | | | | | | | | | | | | - +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+ - C CL CR B BL BR T TL TR */ - -#define GL2PS_TEXT_C 1 -#define GL2PS_TEXT_CL 2 -#define GL2PS_TEXT_CR 3 -#define GL2PS_TEXT_B 4 -#define GL2PS_TEXT_BL 5 -#define GL2PS_TEXT_BR 6 -#define GL2PS_TEXT_T 7 -#define GL2PS_TEXT_TL 8 -#define GL2PS_TEXT_TR 9 - -typedef GLfloat GL2PSrgba[4]; - -#if defined(__cplusplus) -extern "C" { -#endif - -GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, - GLint viewport[4], GLint format, GLint sort, - GLint options, GLint colormode, - GLint colorsize, GL2PSrgba *colormap, - GLint nr, GLint ng, GLint nb, GLint buffersize, - FILE *stream, const char *filename); -GL2PSDLL_API GLint gl2psEndPage(void); -GL2PSDLL_API GLint gl2psSetOptions(GLint options); -GL2PSDLL_API GLint gl2psGetOptions(GLint *options); -GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]); -GL2PSDLL_API GLint gl2psEndViewport(void); -GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, - GLshort fontsize); -GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, - GLshort fontsize, GLint align, GLfloat angle); -GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str); -GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, - GLint xorig, GLint yorig, - GLenum format, GLenum type, const void *pixels); -GL2PSDLL_API GLint gl2psEnable(GLint mode); -GL2PSDLL_API GLint gl2psDisable(GLint mode); -GL2PSDLL_API GLint gl2psPointSize(GLfloat value); -GL2PSDLL_API GLint gl2psLineWidth(GLfloat value); -GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor); - -/* undocumented */ -GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height, - const GLfloat position[3], - const unsigned char *imagemap); -GL2PSDLL_API const char *gl2psGetFileExtension(GLint format); -GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format); - -#if defined(__cplusplus) -} -#endif - -#endif /* __GL2PS_H__ */ diff --git a/gui/gui/inc/TRootCanvas.h b/gui/gui/inc/TRootCanvas.h index 60f70d9663593..fadcd3255177f 100644 --- a/gui/gui/inc/TRootCanvas.h +++ b/gui/gui/inc/TRootCanvas.h @@ -121,6 +121,7 @@ friend class TRootContainer; void SetWindowTitle(const char *newTitle) override; void SetCanvasSize(UInt_t w, UInt_t h) override; void SetStatusText(const char *txt = nullptr, Int_t partidx = 0) override; + void UpdateViewWithMenu(); void Show() override { MapRaised(); } void ShowMenuBar(Bool_t show = kTRUE) override; diff --git a/gui/gui/src/TGGC.cxx b/gui/gui/src/TGGC.cxx index 0078ccf465c5c..7d5b52071a2a9 100644 --- a/gui/gui/src/TGGC.cxx +++ b/gui/gui/src/TGGC.cxx @@ -50,7 +50,6 @@ TGGC::TGGC(GCValues_t *values, Bool_t) } } else { fValues = {}; - fContext = 0; } SetRefCount(1); } @@ -61,20 +60,14 @@ TGGC::TGGC(GCValues_t *values, Bool_t) TGGC::TGGC(GCValues_t *values) { fContext = 0; + SetRefCount(1); // case of default ctor at program startup before gClient exists - if (!values) { + if (!values) fValues = {}; - fContext = 0; - SetRefCount(1); - return; - } - - if (gClient) + else if (gClient) gClient->GetGC(values, kTRUE); - else { - fContext = 0; + else Error("TGGC", "TGClient not yet initialized, should never happen"); - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/gui/gui/src/TGLabel.cxx b/gui/gui/src/TGLabel.cxx index 9c309c0cbf2e1..7875c1c4b2af2 100644 --- a/gui/gui/src/TGLabel.cxx +++ b/gui/gui/src/TGLabel.cxx @@ -340,8 +340,8 @@ void TGLabel::SetTextFont(TGFont *font, Bool_t global) if (!global) { if (gc == &GetDefaultGC() ) { // create new GC gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE); // copy ctor. + fHasOwnFont = kTRUE; } - fHasOwnFont = kTRUE; } if (oldfont != fgDefaultFont) { fClient->FreeFont(oldfont); @@ -366,8 +366,8 @@ void TGLabel::SetTextColor(Pixel_t color, Bool_t global) if (!global) { if (gc == &GetDefaultGC() ) { gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE); // copy + fHasOwnFont = kTRUE; } - fHasOwnFont = kTRUE; } if (gc) { gc->SetForeground(color); diff --git a/gui/gui/src/TGPicture.cxx b/gui/gui/src/TGPicture.cxx index 1b4d74771dc8a..2776dbb6387ce 100644 --- a/gui/gui/src/TGPicture.cxx +++ b/gui/gui/src/TGPicture.cxx @@ -94,42 +94,36 @@ const TGPicture *TGPicturePool::GetPicture(const char *name) TGPicture *pic = (TGPicture *)fPicList->FindObject(pname); if (pic && !pic->IsScaled()) { - if (pic->fPic == kNone) - return 0; + // in batch mode allow to return dummy image + if ((pic->fPic == kNone) && !gROOT->IsBatch()) + return nullptr; pic->AddReference(); return pic; } char *picnam = gSystem->Which(fPath, pname, kReadPermission); - if (!picnam) { - pic = new TGPicture(pname); - pic->fAttributes.fColormap = fClient->GetDefaultColormap(); - pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors - pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness; - fPicList->Add(pic); - return 0; - } - TImage *img = TImage::Open(picnam); + TImage *img = picnam ? TImage::Open(picnam) : nullptr; + + delete [] picnam; + if (!img) { pic = new TGPicture(pname); pic->fAttributes.fColormap = fClient->GetDefaultColormap(); pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness; fPicList->Add(pic); - delete [] picnam; - return 0; + return nullptr; } pic = new TGPicture(pname, img->GetPixmap(), img->GetMask()); - delete [] picnam; delete img; fPicList->Add(pic); return pic; } //////////////////////////////////////////////////////////////////////////////// -/// Like TGPicturePool::GetPicture() but, instead of returning null when the +/// Like TGPicturePool::GetPicture() but, instead of returning null when the /// picture is not found, it returns a valid empty picture. const TGPicture *TGPicturePool::GetPictureOrEmpty(const char *name) diff --git a/gui/gui/src/TRootCanvas.cxx b/gui/gui/src/TRootCanvas.cxx index fdf1c3005d5c9..d9c9908de3591 100644 --- a/gui/gui/src/TRootCanvas.cxx +++ b/gui/gui/src/TRootCanvas.cxx @@ -73,6 +73,45 @@ drawing area. The widgets used are the new native ROOT GUI widgets. #include "HelpText.h" +namespace { + +bool IsGeometryPrimitive(TObject *obj) +{ + static TClass *geoVolumeClass = TClass::GetClass("TGeoVolume"); + static TClass *geoShapeClass = TClass::GetClass("TGeoShape"); + static TClass *geoOverlapClass = TClass::GetClass("TGeoOverlap"); + static TClass *geoTrackClass = TClass::GetClass("TGeoTrack"); + + if (!obj) + return false; + + return (geoVolumeClass && obj->InheritsFrom(geoVolumeClass)) || + (geoShapeClass && obj->InheritsFrom(geoShapeClass)) || + (geoOverlapClass && obj->InheritsFrom(geoOverlapClass)) || + (geoTrackClass && obj->InheritsFrom(geoTrackClass)); +} + +bool PadHasGeometryContent(TVirtualPad *pad) +{ + if (!pad) + return false; + + TList *primitives = pad->GetListOfPrimitives(); + if (!primitives) + return false; + + TIter next(primitives); + while (TObject *obj = next()) { + if (IsGeometryPrimitive(obj)) + return true; + if (obj->InheritsFrom(TVirtualPad::Class()) && PadHasGeometryContent(static_cast(obj))) + return true; + } + + return false; +} + +} // namespace // Canvas menu command ids enum ERootCanvasCommands { @@ -84,6 +123,7 @@ enum ERootCanvasCommands { kFileSaveAsPS, kFileSaveAsEPS, kFileSaveAsPDF, + kFileSaveAsSVG, kFileSaveAsGIF, kFileSaveAsJPG, kFileSaveAsPNG, @@ -263,8 +303,9 @@ TRootContainer::TRootContainer(TRootCanvas *c, Window_t id, const TGWindow *p) kButtonPressMask | kButtonReleaseMask | kPointerMotionMask, kNone, kNone); - AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask | - kExposureMask | kStructureNotifyMask | kLeaveWindowMask); + AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask | kExposureMask | + kStructureNotifyMask | kEnterWindowMask | kLeaveWindowMask); + fEditDisabled = kEditDisable; } @@ -338,11 +379,12 @@ void TRootCanvas::CreateCanvas(const char *name) // Create menus fFileSaveMenu = new TGPopupMenu(fClient->GetDefaultRoot()); - fFileSaveMenu->AddEntry(Form("%s.&ps", name), kFileSaveAsPS); - fFileSaveMenu->AddEntry(Form("%s.&eps", name), kFileSaveAsEPS); - fFileSaveMenu->AddEntry(Form("%s.p&df", name), kFileSaveAsPDF); - fFileSaveMenu->AddEntry(Form("%s.&tex", name), kFileSaveAsTEX); - fFileSaveMenu->AddEntry(Form("%s.&gif", name), kFileSaveAsGIF); + fFileSaveMenu->AddEntry(TString::Format("%s.&ps", name), kFileSaveAsPS); + fFileSaveMenu->AddEntry(TString::Format("%s.&eps", name), kFileSaveAsEPS); + fFileSaveMenu->AddEntry(TString::Format("%s.p&df", name), kFileSaveAsPDF); + fFileSaveMenu->AddEntry(TString::Format("%s.&svg", name), kFileSaveAsSVG); + fFileSaveMenu->AddEntry(TString::Format("%s.&tex", name), kFileSaveAsTEX); + fFileSaveMenu->AddEntry(TString::Format("%s.&gif", name), kFileSaveAsGIF); static Int_t img = 0; @@ -358,12 +400,12 @@ void TRootCanvas::CreateCanvas(const char *name) gErrorIgnoreLevel = sav; } if (img > 0) { - fFileSaveMenu->AddEntry(Form("%s.&jpg",name), kFileSaveAsJPG); - fFileSaveMenu->AddEntry(Form("%s.&png",name), kFileSaveAsPNG); + fFileSaveMenu->AddEntry(TString::Format("%s.&jpg",name), kFileSaveAsJPG); + fFileSaveMenu->AddEntry(TString::Format("%s.&png",name), kFileSaveAsPNG); } - fFileSaveMenu->AddEntry(Form("%s.&C", name), kFileSaveAsC); - fFileSaveMenu->AddEntry(Form("%s.&root",name), kFileSaveAsRoot); + fFileSaveMenu->AddEntry(TString::Format("%s.&C", name), kFileSaveAsC); + fFileSaveMenu->AddEntry(TString::Format("%s.&root",name), kFileSaveAsRoot); fFileMenu = new TGPopupMenu(fClient->GetDefaultRoot()); fFileMenu->AddEntry("&New Canvas", kFileNewCanvas); @@ -473,6 +515,7 @@ void TRootCanvas::CreateCanvas(const char *name) fEditClearMenu->Associate(this); fViewMenu->Associate(this); fViewWithMenu->Associate(this); + fViewWithMenu->Connect("PoppedUp()", "TRootCanvas", this, "UpdateViewWithMenu()"); fOptionMenu->Associate(this); fToolsMenu->Associate(this); fHelpMenu->Associate(this); @@ -935,6 +978,9 @@ Bool_t TRootCanvas::ProcessMessage(Longptr_t msg, Longptr_t parm1, Longptr_t) case kFileSaveAsPDF: fCanvas->SaveAs(".pdf"); break; + case kFileSaveAsSVG: + fCanvas->SaveAs(".svg"); + break; case kFileSaveAsGIF: fCanvas->SaveAs(".gif"); break; @@ -1044,9 +1090,14 @@ Bool_t TRootCanvas::ProcessMessage(Longptr_t msg, Longptr_t parm1, Longptr_t) case kViewIconify: Iconify(); break; - case kViewX3D: - gPad->GetViewer3D("x3d"); + case kViewX3D: { + TVirtualPad *pad = gPad ? gPad : (fCanvas ? fCanvas->GetSelectedPad() : nullptr); + if (!pad) + pad = fCanvas; + if (!PadHasGeometryContent(pad)) + pad->GetViewer3D("x3d"); break; + } case kViewOpenGL: gPad->GetViewer3D("ogl"); break; @@ -1329,7 +1380,7 @@ void TRootCanvas::SetWindowTitle(const char *title) { SetWindowName(title); SetIconName(title); - fToolDock->SetWindowName(Form("ToolBar: %s", title)); + fToolDock->SetWindowName(TString::Format("ToolBar: %s", title)); } //////////////////////////////////////////////////////////////////////////////// @@ -1617,7 +1668,7 @@ void TRootCanvas::ShowToolBar(Bool_t show) } fToolDock->MapSubwindows(); fToolDock->Layout(); - fToolDock->SetWindowName(Form("ToolBar: %s", GetWindowName())); + fToolDock->SetWindowName(TString::Format("ToolBar: %s", GetWindowName())); fToolDock->Connect("Docked()", "TRootCanvas", this, "AdjustSize()"); fToolDock->Connect("Undocked()", "TRootCanvas", this, "AdjustSize()"); } @@ -1745,7 +1796,7 @@ Bool_t TRootCanvas::HandleContainerButton(Event_t *event) if (event->fType == kButtonPress) { if (fToolTip && fCanvas->GetShowToolTips()) { fToolTip->Hide(); - gVirtualX->UpdateWindow(0); + gVirtualX->UpdateWindowW(gVirtualX->GetWindowContext(fCanvasID), 0); gSystem->ProcessEvents(); } fButton = button; @@ -1968,6 +2019,9 @@ Bool_t TRootCanvas::HandleContainerCrossing(Event_t *event) if (event->fType == kLeaveNotify && event->fCode == kNotifyNormal) fCanvas->HandleInput(kMouseLeave, x, y); + if (event->fType == kEnterNotify && event->fCode == kNotifyNormal) + fCanvas->HandleInput(kMouseEnter, x, y); + return kTRUE; } @@ -1986,7 +2040,7 @@ Bool_t TRootCanvas::HandleDNDDrop(TDNDData *data) if (!obj) return kTRUE; gPad->Clear(); if (obj->InheritsFrom("TKey")) { - TObject *object = (TObject *)gROOT->ProcessLine(Form("((TKey *)0x%zx)->ReadObj();", (size_t)obj)); + TObject *object = (TObject *)gROOT->ProcessLine(TString::Format("((TKey *)0x%zx)->ReadObj();", (size_t)obj)); if (!object) return kTRUE; if (object->InheritsFrom("TGraph")) object->Draw("ALP"); @@ -2093,6 +2147,21 @@ void TRootCanvas::Activated(Int_t id) } } +//////////////////////////////////////////////////////////////////////////////// +/// Update the "View With" submenu based on the currently selected pad content. + +void TRootCanvas::UpdateViewWithMenu() +{ + TVirtualPad *pad = fCanvas ? fCanvas->GetSelectedPad() : nullptr; + if (!pad) + pad = fCanvas; + + if (PadHasGeometryContent(pad)) + fViewWithMenu->DisableEntry(kViewX3D); + else + fViewWithMenu->EnableEntry(kViewX3D); +} + //////////////////////////////////////////////////////////////////////////////// /// Save a canvas container as a C++ statement(s) on output stream out. diff --git a/gui/gui/src/TRootEmbeddedCanvas.cxx b/gui/gui/src/TRootEmbeddedCanvas.cxx index 4466c68a64cd9..bcd9588bbd862 100644 --- a/gui/gui/src/TRootEmbeddedCanvas.cxx +++ b/gui/gui/src/TRootEmbeddedCanvas.cxx @@ -84,7 +84,7 @@ TRootEmbeddedContainer::TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t kPointerMotionMask, kNone, kNone); AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask | - kExposureMask | kStructureNotifyMask | kLeaveWindowMask); + kExposureMask | kStructureNotifyMask | kEnterWindowMask | kLeaveWindowMask); fEditDisabled = kEditDisableGrab; } @@ -419,6 +419,9 @@ Bool_t TRootEmbeddedCanvas::HandleContainerCrossing(Event_t *event) if (event->fType == kLeaveNotify && event->fCode == kNotifyNormal) fCanvas->HandleInput(kMouseLeave, x, y); + if (event->fType == kEnterNotify && event->fCode == kNotifyNormal) + fCanvas->HandleInput(kMouseEnter, x, y); + return kTRUE; } diff --git a/gui/webgui6/CMakeLists.txt b/gui/webgui6/CMakeLists.txt index 0288b33ceed77..0540870b27119 100644 --- a/gui/webgui6/CMakeLists.txt +++ b/gui/webgui6/CMakeLists.txt @@ -16,7 +16,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(WebGui6 TWebPadOptions.h TWebPadPainter.h TWebPainting.h - TWebPS.h TWebSnapshot.h SOURCES src/TWebCanvas.cxx @@ -24,7 +23,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(WebGui6 src/TWebMenuItem.cxx src/TWebPadPainter.cxx src/TWebPainting.cxx - src/TWebPS.cxx src/TWebSnapshot.cxx DEPENDENCIES Core diff --git a/gui/webgui6/inc/LinkDef.h b/gui/webgui6/inc/LinkDef.h index e1e4f25b4ddd5..6d10160421b91 100644 --- a/gui/webgui6/inc/LinkDef.h +++ b/gui/webgui6/inc/LinkDef.h @@ -25,7 +25,6 @@ #pragma link C++ class TWebPadClick+; #pragma link C++ class TWebPadPainter+; -#pragma link C++ class TWebPS+; #pragma link C++ class TWebPainting+; #pragma link C++ class TWebSnapshot+; #pragma link C++ class TPadWebSnapshot+; diff --git a/gui/webgui6/inc/TWebCanvas.h b/gui/webgui6/inc/TWebCanvas.h index 021fd7b820e1f..7f5cb595c5146 100644 --- a/gui/webgui6/inc/TWebCanvas.h +++ b/gui/webgui6/inc/TWebCanvas.h @@ -27,7 +27,7 @@ class TPad; class TPadWebSnapshot; -class TWebPS; +class TWebPainting; class TObjLink; class TExec; class TWebCanvasTimer; @@ -139,7 +139,7 @@ friend class TWebCanvasTimer; void AddColorsPalette(TPadWebSnapshot &master); void AddCustomFonts(TPadWebSnapshot &master); - void CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObject *obj, const char *opt, TWebPS *masterps = nullptr); + void CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObject *obj, const char *opt, TWebPainting *masterps = nullptr); void CreatePadSnapshot(TPadWebSnapshot &paddata, TPad *pad, Long64_t version, PadPaintingReady_t func); void CheckPadModified(TPad *pad); diff --git a/gui/webgui6/inc/TWebPS.h b/gui/webgui6/inc/TWebPS.h deleted file mode 100644 index 6db3f47aea0a6..0000000000000 --- a/gui/webgui6/inc/TWebPS.h +++ /dev/null @@ -1,72 +0,0 @@ -// Author: Sergey Linev, GSI 23/10/2018 - -/************************************************************************* - * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_TWebPS -#define ROOT_TWebPS - -#include "TVirtualPS.h" - -#include "TWebPainting.h" - -#include -#include - -class TWebPS : public TVirtualPS { - - std::unique_ptr fPainting; ///!< object to store all painting - - enum EAttrKinds { attrLine = 0x1, attrFill = 0x2, attrMarker = 0x4, attrText = 0x8 }; - - Float_t *StoreOperation(const std::string &oper, unsigned attrkind, int opersize = 0); - -public: - TWebPS(); - - Bool_t IsEmptyPainting() const { return fPainting ? fPainting->IsEmpty() : kTRUE; } - TWebPainting *GetPainting() { return fPainting.get(); } - TWebPainting *TakePainting() - { - fPainting->FixSize(); - return fPainting.release(); - } - void CreatePainting(); - - /// not yet implemented - - void CellArrayBegin(Int_t, Int_t, Double_t, Double_t, Double_t, Double_t) override {} - void CellArrayFill(Int_t, Int_t, Int_t) override {} - void CellArrayEnd() override {} - void Close(Option_t * = "") override {} - void DrawFrame(Double_t, Double_t, Double_t, Double_t, Int_t, Int_t, Int_t, Int_t) override {} - void NewPage() override {} - void Open(const char *, Int_t = -111) override {} - void SetColor(Float_t, Float_t, Float_t) override {} - - // overwritten methods - void DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override; - void DrawPolyMarker(Int_t n, Float_t *x, Float_t *y) override; - void DrawPolyMarker(Int_t n, Double_t *x, Double_t *y) override; - void DrawPS(Int_t n, Float_t *xw, Float_t *yw) override; - void DrawPS(Int_t n, Double_t *xw, Double_t *yw) override; - void Text(Double_t x, Double_t y, const char *str) override; - void Text(Double_t x, Double_t y, const wchar_t *str) override; - void TextUrl(Double_t x, Double_t y, const char *string, const char *url) override; - -private: - //Let's make this clear: - TWebPS(const TWebPS &rhs) = delete; - TWebPS(TWebPS && rhs) = delete; - TWebPS & operator = (const TWebPS &rhs) = delete; - TWebPS & operator = (TWebPS && rhs) = delete; - - ClassDefOverride(TWebPS, 0) // Redirection of VirtualPS to Web painter -}; - -#endif diff --git a/gui/webgui6/inc/TWebPadPainter.h b/gui/webgui6/inc/TWebPadPainter.h index 64a0bafd5fee7..90a81773ea734 100644 --- a/gui/webgui6/inc/TWebPadPainter.h +++ b/gui/webgui6/inc/TWebPadPainter.h @@ -11,27 +11,21 @@ #ifndef ROOT_TWebPadPainter #define ROOT_TWebPadPainter -#include "TVirtualPadPainter.h" +#include "TPadPainterBase.h" -#include "TAttLine.h" -#include "TAttFill.h" -#include "TAttText.h" -#include "TAttMarker.h" #include #include "TWebPainting.h" -#include "TWebPS.h" class TWebCanvas; -class TWebPadPainter : public TVirtualPadPainter, public TAttLine, public TAttFill, public TAttText, public TAttMarker { +class TWebPadPainter : public TPadPainterBase { friend class TWebCanvas; protected: TWebPainting *fPainting{nullptr}; ///GetLineColor() : TAttLine::GetLineColor(); } - Style_t GetLineStyle() const override { return fPS ? fPS->GetLineStyle() : TAttLine::GetLineStyle(); } - Width_t GetLineWidth() const override { return fPS ? fPS->GetLineWidth() : TAttLine::GetLineWidth(); } - - void SetLineColor(Color_t lcolor) override { if (fPS) fPS->SetLineColor(lcolor); else TAttLine::SetLineColor(lcolor); } - void SetLineStyle(Style_t lstyle) override { if (fPS) fPS->SetLineStyle(lstyle); else TAttLine::SetLineStyle(lstyle); } - void SetLineWidth(Width_t lwidth) override { if (fPS) fPS->SetLineWidth(lwidth); else TAttLine::SetLineWidth(lwidth); } - - //Fill attributes. - Color_t GetFillColor() const override { return fPS ? fPS->GetFillColor() : TAttFill::GetFillColor(); } - Style_t GetFillStyle() const override { return fPS ? fPS->GetFillStyle() : TAttFill::GetFillStyle(); } - Bool_t IsTransparent() const override { return fPS ? fPS->IsTransparent() : TAttFill::IsTransparent(); } - - void SetFillColor(Color_t fcolor) override { if (fPS) fPS->SetFillColor(fcolor); else TAttFill::SetFillColor(fcolor); } - void SetFillStyle(Style_t fstyle) override { if (fPS) fPS->SetFillStyle(fstyle); else TAttFill::SetFillStyle(fstyle); } - void SetOpacity(Int_t percent) override { if (fPS) fPS->SetFillStyle(4000 + percent); else TAttFill::SetFillStyle(4000 + percent); } - - //Text attributes. - Short_t GetTextAlign() const override { return fPS ? fPS->GetTextAlign() : TAttText::GetTextAlign(); } - Float_t GetTextAngle() const override { return fPS ? fPS->GetTextAngle() : TAttText::GetTextAngle(); } - Color_t GetTextColor() const override { return fPS ? fPS->GetTextColor() : TAttText::GetTextColor(); } - Font_t GetTextFont() const override { return fPS ? fPS->GetTextFont() : TAttText::GetTextFont(); } - Float_t GetTextSize() const override { return fPS ? fPS->GetTextSize() : TAttText::GetTextSize(); } - Float_t GetTextMagnitude() const override { return 0; } - - void SetTextAlign(Short_t align) override { if (fPS) fPS->SetTextAlign(align); else TAttText::SetTextAlign(align); } - void SetTextAngle(Float_t tangle) override { if (fPS) fPS->SetTextAngle(tangle); else TAttText::SetTextAngle(tangle); } - void SetTextColor(Color_t tcolor) override { if (fPS) fPS->SetTextColor(tcolor); else TAttText::SetTextColor(tcolor); } - void SetTextFont(Font_t tfont) override { if (fPS) fPS->SetTextFont(tfont); else TAttText::SetTextFont(tfont); } - void SetTextSize(Float_t tsize) override { if (fPS) fPS->SetTextSize(tsize); else TAttText::SetTextSize(tsize); } - void SetTextSizePixels(Int_t npixels) override { if (fPS) fPS->SetTextSizePixels(npixels); else TAttText::SetTextSizePixels(npixels); } - - //Marker attributes - Color_t GetMarkerColor() const override { return fPS ? fPS->GetMarkerColor() : TAttMarker::GetMarkerColor(); } - Style_t GetMarkerStyle() const override { return fPS ? fPS->GetMarkerStyle() : TAttMarker::GetMarkerStyle(); } - Size_t GetMarkerSize() const override { return fPS ? fPS->GetMarkerSize() : TAttMarker::GetMarkerSize(); } - - void SetMarkerColor(Color_t mcolor) override { if (fPS) fPS->SetMarkerColor(mcolor); else TAttMarker::SetMarkerColor(mcolor); } - void SetMarkerStyle(Style_t mstyle) override { if (fPS) fPS->SetMarkerStyle(mstyle); else TAttMarker::SetMarkerStyle(mstyle); } - void SetMarkerSize(Size_t msize) override { if (fPS) fPS->SetMarkerSize(msize); else TAttMarker::SetMarkerSize(msize); } + void SetPainting(TWebPainting *p) { fPainting = p; } + + + void SetOpacity(Int_t percent) override; //2. "Off-screen management" part. Int_t CreateDrawable(UInt_t, UInt_t) override { return -1; } @@ -125,6 +78,8 @@ friend class TWebCanvas; void DrawTextUrl(Double_t x, Double_t y, const char *text, const char *url) override; + Bool_t IsSupportAlpha() const override { return kTRUE; } + private: //Let's make this clear: TWebPadPainter(const TWebPadPainter &rhs) = delete; diff --git a/gui/webgui6/src/TWebCanvas.cxx b/gui/webgui6/src/TWebCanvas.cxx index 71be3179588ca..82b84d3512651 100644 --- a/gui/webgui6/src/TWebCanvas.cxx +++ b/gui/webgui6/src/TWebCanvas.cxx @@ -12,7 +12,6 @@ #include "TWebSnapshot.h" #include "TWebPadPainter.h" -#include "TWebPS.h" #include "TWebMenuItem.h" #include "ROOT/RWebWindowsManager.hxx" #include "THttpServer.h" @@ -54,6 +53,7 @@ #include "TView.h" #include "TExec.h" #include "TVirtualX.h" +#include "TVirtualPS.h" #include "TMath.h" #include "TTimer.h" #include "TThread.h" @@ -511,7 +511,7 @@ bool TWebCanvas::IsCustomClass(const TClass *cl) ////////////////////////////////////////////////////////////////////////////////////////////////// /// Creates representation of the object for painting in web browser -void TWebCanvas::CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObject *obj, const char *opt, TWebPS *masterps) +void TWebCanvas::CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObject *obj, const char *opt, TWebPainting *masterps) { if (IsJSSupportedClass(obj, masterps != nullptr)) { master.NewPrimitive(obj, opt).SetSnapshot(TWebSnapshot::kObject, obj); @@ -538,15 +538,15 @@ void TWebCanvas::CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObjec TVirtualPS *saveps = gVirtualPS; - TWebPS *webps = masterps; + auto painting = masterps; if (!masterps) { - webps = new TWebPS; - webps->GetPainting()->SetClassName(obj->ClassName()); - webps->GetPainting()->SetObjectName(obj->GetName()); + painting = new TWebPainting; + painting->SetClassName(obj->ClassName()); + painting->SetObjectName(obj->GetName()); } - gVirtualPS = webps; + gVirtualPS = nullptr; if (painter) - painter->SetPainting(webps->GetPainting(), webps); + painter->SetPainting(painting); // calling Paint function for the object obj->Paint(opt); @@ -559,7 +559,7 @@ void TWebCanvas::CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObjec } if (painter) - painter->SetPainting(nullptr, nullptr); + painter->SetPainting(nullptr); gVirtualPS = saveps; @@ -567,9 +567,10 @@ void TWebCanvas::CreateObjectSnapshot(TPadWebSnapshot &master, TPad *pad, TObjec // if there are master PS, do not create separate entries if (!masterps) { - if (!webps->IsEmptyPainting()) - master.NewPrimitive(obj, opt).SetSnapshot(TWebSnapshot::kSVG, webps->TakePainting(), kTRUE); - delete webps; + if (!painting->IsEmpty()) + master.NewPrimitive(obj, opt).SetSnapshot(TWebSnapshot::kSVG, painting, kTRUE); + else + delete painting; } } @@ -685,7 +686,7 @@ void TWebCanvas::CreatePadSnapshot(TPadWebSnapshot &paddata, TPad *pad, Long64_t TList *primitives = pad->GetListOfPrimitives(); - TWebPS masterps; + auto masterps = std::make_unique(); bool usemaster = primitives ? (primitives->GetSize() > fPrimitivesMerge) : false; TIter iter(primitives); @@ -833,10 +834,10 @@ void TWebCanvas::CreatePadSnapshot(TPadWebSnapshot &paddata, TPad *pad, Long64_t primitives->Add(polargram, polargram_drawopt); auto flush_master = [&]() { - if (!usemaster || masterps.IsEmptyPainting()) return; + if (!usemaster || masterps->IsEmpty()) return; - paddata.NewPrimitive(pad).SetSnapshot(TWebSnapshot::kSVG, masterps.TakePainting(), kTRUE); - masterps.CreatePainting(); // create for next operations + paddata.NewPrimitive(pad).SetSnapshot(TWebSnapshot::kSVG, masterps.release(), kTRUE); + masterps = std::make_unique(); // create for next operations }; auto check_cutg_in_options = [&](const TString &opt) { @@ -1156,7 +1157,7 @@ void TWebCanvas::CreatePadSnapshot(TPadWebSnapshot &paddata, TPad *pad, Long64_t flush_master(); paddata.NewPrimitive(obj, iter.GetOption()).SetSnapshot(TWebSnapshot::kObject, obj); } else { - CreateObjectSnapshot(paddata, pad, obj, iter.GetOption(), usemaster ? &masterps : nullptr); + CreateObjectSnapshot(paddata, pad, obj, iter.GetOption(), usemaster ? masterps.get() : nullptr); } } @@ -1794,8 +1795,7 @@ void TWebCanvas::ProcessExecs(TPad *pad, TExec *extra) return; auto saveps = gVirtualPS; - TWebPS ps; - gVirtualPS = &ps; + gVirtualPS = nullptr; auto savex = gVirtualX; TVirtualX x; diff --git a/gui/webgui6/src/TWebPS.cxx b/gui/webgui6/src/TWebPS.cxx deleted file mode 100644 index a10b7062baa37..0000000000000 --- a/gui/webgui6/src/TWebPS.cxx +++ /dev/null @@ -1,137 +0,0 @@ -// Author: Sergey Linev, GSI 23/10/2018 - -/************************************************************************* - * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#include "TWebPS.h" - -#include - -/** \class TWebPS -\ingroup webgui6 - -*/ - - -TWebPS::TWebPS() -{ - CreatePainting(); -} - -void TWebPS::CreatePainting() -{ - fPainting = std::make_unique(); -} - - -Float_t *TWebPS::StoreOperation(const std::string &oper, unsigned attrkind, int opersize) -{ - if (attrkind & attrLine) - fPainting->AddLineAttr(*this); - - if (attrkind & attrFill) - fPainting->AddFillAttr(*this); - - if (attrkind & attrMarker) - fPainting->AddMarkerAttr(*this); - - if (attrkind & attrText) - fPainting->AddTextAttr(*this); - - fPainting->AddOper(oper); - - return fPainting->Reserve(opersize); -} - -void TWebPS::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2) -{ - Float_t *buf = (GetFillStyle() > 0) ? StoreOperation("b", attrFill, 4) : StoreOperation("r", attrLine, 4); - - buf[0] = x1; - buf[1] = y1; - buf[2] = x2; - buf[3] = y2; -} - -void TWebPS::DrawPolyMarker(Int_t nPoints, Float_t *x, Float_t *y) -{ - if (nPoints < 1) return; - - Float_t *buf = StoreOperation(std::string("m") + std::to_string(nPoints), attrLine | attrMarker, nPoints*2); - - for (Int_t n=0;nAddLineAttr(fPS ? *((TAttLine *) fPS) : *((TAttLine *)this)); + fPainting->AddLineAttr(GetAttLine()); if (attrkind & attrFill) - fPainting->AddFillAttr(fPS ? *((TAttFill *) fPS) : *((TAttFill *)this)); + fPainting->AddFillAttr(GetAttFill()); if (attrkind & attrMarker) - fPainting->AddMarkerAttr(fPS ? *((TAttMarker *) fPS) : *((TAttMarker *)this)); + fPainting->AddMarkerAttr(GetAttMarker()); if (attrkind & attrText) - fPainting->AddTextAttr(fPS ? *((TAttText *)fPS) : *((TAttText *)this)); + fPainting->AddTextAttr(GetAttText()); fPainting->AddOper(oper); @@ -65,7 +72,7 @@ void TWebPadPainter::DrawPixels(const unsigned char * /*pixelData*/, UInt_t /*wi void TWebPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) { - if (GetLineWidth() <= 0) + if (GetAttLine().GetLineWidth() <= 0) return; auto buf = StoreOperation("l2", attrLine, 4); @@ -83,7 +90,8 @@ void TWebPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2 void TWebPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) { - if (GetLineWidth()<=0) return; + if (GetAttLine().GetLineWidth() <= 0) + return; ::Error("DrawLineNDC", "Not supported correctly"); @@ -102,7 +110,8 @@ void TWebPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t void TWebPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode) { - if (GetLineWidth()<=0 && mode == TVirtualPadPainter::kHollow) return; + if (GetAttLine().GetLineWidth() <= 0 && mode == TVirtualPadPainter::kHollow) + return; Float_t *buf = nullptr; @@ -124,7 +133,7 @@ void TWebPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, void TWebPadPainter::DrawFillArea(Int_t nPoints, const Double_t *xs, const Double_t *ys) { - if ((GetFillStyle() <= 0) || (nPoints < 3)) + if ((GetAttFill().GetFillStyle() <= 0) || (nPoints < 3)) return; auto buf = StoreOperation("f" + std::to_string(nPoints), attrFill, nPoints * 2); @@ -140,7 +149,7 @@ void TWebPadPainter::DrawFillArea(Int_t nPoints, const Double_t *xs, const Doubl void TWebPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_t *ys) { - if ((GetFillStyle() <= 0) || (nPoints < 3)) + if ((GetAttFill().GetFillStyle() <= 0) || (nPoints < 3)) return; auto buf = StoreOperation("f" + std::to_string(nPoints), attrFill, nPoints * 2); @@ -156,7 +165,7 @@ void TWebPadPainter::DrawFillArea(Int_t nPoints, const Float_t *xs, const Float_ void TWebPadPainter::DrawPolyLine(Int_t nPoints, const Double_t *xs, const Double_t *ys) { - if ((GetLineWidth() <= 0) || (nPoints < 2)) + if ((GetAttLine().GetLineWidth() <= 0) || (nPoints < 2)) return; auto buf = StoreOperation("l" + std::to_string(nPoints), attrLine, nPoints * 2); @@ -172,7 +181,7 @@ void TWebPadPainter::DrawPolyLine(Int_t nPoints, const Double_t *xs, const Doubl void TWebPadPainter::DrawPolyLine(Int_t nPoints, const Float_t *xs, const Float_t *ys) { - if ((GetLineWidth() <= 0) || (nPoints < 2)) + if ((GetAttLine().GetLineWidth() <= 0) || (nPoints < 2)) return; auto buf = StoreOperation("l" + std::to_string(nPoints), attrLine, nPoints * 2); @@ -188,7 +197,7 @@ void TWebPadPainter::DrawPolyLine(Int_t nPoints, const Float_t *xs, const Float_ void TWebPadPainter::DrawPolyLineNDC(Int_t nPoints, const Double_t *u, const Double_t *v) { - if ((GetLineWidth() <= 0) || (nPoints < 2)) + if ((GetAttLine().GetLineWidth() <= 0) || (nPoints < 2)) return; ::Error("DrawPolyLineNDC", "Not supported correctly"); diff --git a/hist/hist/src/TFormula.cxx b/hist/hist/src/TFormula.cxx index cb4998da3cf3e..376c4ae49c276 100644 --- a/hist/hist/src/TFormula.cxx +++ b/hist/hist/src/TFormula.cxx @@ -240,6 +240,7 @@ std::string vectorizedArgType() 2. Two Dimensional functions: - `xygaus` is a substitute for `[Constant]*exp(-0.5*pow(((x-[MeanX])/[SigmaX]),2 )- 0.5*pow(((y-[MeanY])/[SigmaY]),2))`, a 2d Gaussian without correlation. - `bigaus` is a substitute for `[Constant]*ROOT::Math::bigaussian_pdf (x,y,[SigmaX],[SigmaY],[Rho],[MeanX],[MeanY])`, a 2d gaussian including a correlation parameter. + Note the different order of parameters for bigaus: [Constant]=[0], [SigmaX]=[2], [SigmaY]=[4], [Rho]=[5], [MeanX]=[1], [MeanY]=[3] 3. Three Dimensional functions: - `xyzgaus` is for a 3d Gaussians without correlations: `[Constant]*exp(-0.5*pow(((x-[MeanX])/[SigmaX]),2 )- 0.5*pow(((y-[MeanY])/[SigmaY]),2 )- 0.5*pow(((z-[MeanZ])/[SigmaZ]),2))` diff --git a/hist/histv7/doc/CodeArchitecture.md b/hist/histv7/doc/CodeArchitecture.md index 15bd648dc7291..0cb28176b5150 100644 --- a/hist/histv7/doc/CodeArchitecture.md +++ b/hist/histv7/doc/CodeArchitecture.md @@ -79,7 +79,7 @@ Each instance has a local `RHistStats` object to avoid contention on the global A single bin index, which is just an integer for normal bins. `Underflow()` and `Overflow()` are special values and not ordered with respect to others. -Objects of this type are passed by value; most notably to `GetBinContent`. +Objects of this type are passed by value; most notably to `GetBinContent` and `SetBinContent`. ### `RBinIndexRange` diff --git a/hist/histv7/doc/DesignImplementation.md b/hist/histv7/doc/DesignImplementation.md index e58b776d89ac2..836abf60c9b90 100644 --- a/hist/histv7/doc/DesignImplementation.md +++ b/hist/histv7/doc/DesignImplementation.md @@ -58,10 +58,12 @@ Special arguments are passed last. For example ```cpp template void Fill(const std::tuple &args, RWeight w); +template void SetBinContent(const std::array &indices, const V &value); ``` -The same works for the variadic function templates that will check the type of the last argument. +Note that we accept mandatory arguments with a template type as well to allow automatic conversion. -For profiles, we accept the value with a template type as well to allow automatic conversion to `double`, for example from `int`. +Variadic function templates receive all arguments in a single function parameter pack. +For optional arguments, the function will check the type of the last argument to determine if it was passed. ## Miscellaneous diff --git a/hist/histv7/inc/ROOT/RAxisVariant.hxx b/hist/histv7/inc/ROOT/RAxisVariant.hxx index e912bd35dbaed..9884003460c6e 100644 --- a/hist/histv7/inc/ROOT/RAxisVariant.hxx +++ b/hist/histv7/inc/ROOT/RAxisVariant.hxx @@ -127,6 +127,26 @@ public: } } + /// Slice this axis according to the specification. + /// + /// Axes throw exceptions if the slicing cannot be performed. For example, the rebin operation must divide the + /// number of normal bins for RRegularAxis and RVariableBinAxis, while RCategoricalAxis cannot be sliced at all. + /// + /// \param[in] sliceSpec the slice specification + /// \return the sliced axis + RAxisVariant Slice(const RSliceSpec &sliceSpec) const + { + if (auto *regular = GetRegularAxis()) { + return regular->Slice(sliceSpec); + } else if (auto *variable = GetVariableBinAxis()) { + return variable->Slice(sliceSpec); + } else if (auto *categorical = GetCategoricalAxis()) { + return categorical->Slice(sliceSpec); + } else { + throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE + } + } + friend bool operator==(const RAxisVariant &lhs, const RAxisVariant &rhs) { return lhs.fVariant == rhs.fVariant; } /// %ROOT Streamer function to throw when trying to store an object of this class. diff --git a/hist/histv7/inc/ROOT/RCategoricalAxis.hxx b/hist/histv7/inc/ROOT/RCategoricalAxis.hxx index 60bb4fe69c4f7..5cb161562f6bb 100644 --- a/hist/histv7/inc/ROOT/RCategoricalAxis.hxx +++ b/hist/histv7/inc/ROOT/RCategoricalAxis.hxx @@ -8,6 +8,7 @@ #include "RBinIndex.hxx" #include "RBinIndexRange.hxx" #include "RLinearizedIndex.hxx" +#include "RSliceSpec.hxx" #include #include @@ -167,6 +168,31 @@ public: : GetNormalRange(); } + /// Slice this axis according to the specification. + /// + /// A categorical axis cannot be sliced. The method will throw if a specification other than the default slice + /// operation is passed. + /// + /// \param[in] sliceSpec the slice specification + /// \return the sliced / copied axis + RCategoricalAxis Slice(const RSliceSpec &sliceSpec) const + { + if (sliceSpec.GetOperationSum() != nullptr) { + throw std::runtime_error("sum operation makes dimension disappear"); + } + + if (!sliceSpec.GetRange().IsInvalid()) { + throw std::runtime_error("slicing of RCategoricalAxis not implemented"); + } + if (sliceSpec.GetOperationRebin() != nullptr) { + throw std::runtime_error("cannot rebin RCategoricalAxis"); + } + + // The sliced axis always has flow bins enabled, for symmetry with other axis types. + bool enableOverflowBin = true; + return RCategoricalAxis(fCategories, enableOverflowBin); + } + /// %ROOT Streamer function to throw when trying to store an object of this class. void Streamer(TBuffer &) { throw std::runtime_error("unable to store RCategoricalAxis"); } }; diff --git a/hist/histv7/inc/ROOT/RHist.hxx b/hist/histv7/inc/ROOT/RHist.hxx index 9054e00b91e6e..10fa9cc679782 100644 --- a/hist/histv7/inc/ROOT/RHist.hxx +++ b/hist/histv7/inc/ROOT/RHist.hxx @@ -238,6 +238,64 @@ public: /// \return the multidimensional range RBinIndexMultiDimRange GetFullMultiDimRange() const { return fEngine.GetFullMultiDimRange(); } + /// Set the content of a single bin. + /// + /// \code + /// ROOT::Experimental::RHist hist({/* two dimensions */}); + /// std::array indices = {3, 5}; + /// int value = /* ... */; + /// hist.SetBinContent(indices, value); + /// \endcode + /// + /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special + /// values. See also the class documentation of RBinIndex. + /// + /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found. + /// + /// \warning Setting the bin content will taint the global histogram statistics. Attempting to access its values, for + /// example calling GetNEntries(), will throw exceptions. + /// + /// \param[in] indices the array of indices for each axis + /// \param[in] value the new value of the bin content + /// \par See also + /// the \ref SetBinContent(const A &... args) const "variadic function template overload" accepting arguments + /// directly + template + void SetBinContent(const std::array &indices, const V &value) + { + fEngine.SetBinContent(indices, value); + fStats.Taint(); + } + + /// Set the content of a single bin. + /// + /// \code + /// ROOT::Experimental::RHist hist({/* two dimensions */}); + /// int value = /* ... */; + /// hist.SetBinContent(ROOT::Experimental::RBinIndex(3), ROOT::Experimental::RBinIndex(5), value); + /// // ... or construct the RBinIndex arguments implicitly from integers: + /// hist.SetBinContent(3, 5, value); + /// \endcode + /// + /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special + /// values. See also the class documentation of RBinIndex. + /// + /// Throws an exception if the number of arguments does not match the axis configuration or the bin is not found. + /// + /// \warning Setting the bin content will taint the global histogram statistics. Attempting to access its values, for + /// example calling GetNEntries(), will throw exceptions. + /// + /// \param[in] args the arguments for each axis and the new value of the bin content + /// \par See also + /// the \ref SetBinContent(const std::array &indices, const V &value) const "function overload" + /// accepting `std::array` + template + void SetBinContent(const A &...args) + { + fEngine.SetBinContent(args...); + fStats.Taint(); + } + /// Add all bin contents and statistics of another histogram. /// /// Throws an exception if the axes configurations are not identical. @@ -393,6 +451,115 @@ public: fStats.Scale(factor); } + /// Slice this histogram with an RSliceSpec per dimension. + /// + /// With a range, only the specified bins are retained. All other bin contents are transferred to the underflow and + /// overflow bins: + /// \code + /// ROOT::Experimental::RHist hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto sliced = hist.Slice({hist.GetAxes()[0].GetNormalRange(1, 5)}); + /// // The returned histogram will have 4 normal bins, an underflow and an overflow bin. + /// \endcode + /// + /// Slicing can also perform operations per dimension, see RSliceSpec. RSliceSpec::ROperationRebin allows to rebin + /// the histogram axis, grouping a number of normal bins into a new one: + /// \code + /// ROOT::Experimental::RHist hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto rebinned = hist.Slice(ROOT::Experimental::RSliceSpec::ROperationRebin(2)); + /// // The returned histogram has groups of two normal bins merged. + /// \endcode + /// + /// RSliceSpec::ROperationSum sums the bin contents along that axis, which allows to project to a lower-dimensional + /// histogram: + /// \code + /// ROOT::Experimental::RHist hist({/* two dimensions */}); + /// // Fill the histogram with a number of entries... + /// auto projected = hist.Slice(ROOT::Experimental::RSliceSpec{}, ROOT::Experimental::RSliceSpec::ROperationSum{}); + /// // The returned histogram has one dimension, with bin contents summed along the second axis. + /// \endcode + /// Note that it is not allowed to sum along all histogram axes because the return value would be a scalar. + /// + /// Ranges and operations can be combined. In that case, the range is applied before the operation. + /// + /// \warning Combining a range and the sum operation drops bin contents, which will taint the global histogram + /// statistics. Attempting to access its values, for example calling GetNEntries(), will throw exceptions. + /// + /// \param[in] sliceSpecs the slice specifications for each axis + /// \return the sliced histogram + /// \par See also + /// the \ref Slice(const A &... args) const "variadic function template overload" accepting arguments directly + RHist Slice(const std::vector &sliceSpecs) const + { + bool dropped = false; + RHist sliced(fEngine.SliceImpl(sliceSpecs, dropped)); + assert(sliced.fStats.GetNDimensions() == sliced.GetNDimensions()); + if (dropped || fStats.IsTainted()) { + sliced.fStats.Taint(); + } else { + sliced.fStats.fNEntries = fStats.fNEntries; + sliced.fStats.fSumW = fStats.fSumW; + sliced.fStats.fSumW2 = fStats.fSumW2; + std::size_t slicedDim = 0; + for (std::size_t i = 0; i < sliceSpecs.size(); i++) { + // A sum operation makes the dimension disappear. + if (sliceSpecs[i].GetOperationSum() == nullptr) { + sliced.fStats.fDimensionStats[slicedDim] = fStats.fDimensionStats[i]; + slicedDim++; + } + } + assert(slicedDim == sliced.GetNDimensions()); + } + return sliced; + } + + /// Slice this histogram with an RSliceSpec per dimension. + /// + /// With a range, only the specified bins are retained. All other bin contents are transferred to the underflow and + /// overflow bins: + /// \code + /// ROOT::Experimental::RHist hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto sliced = hist.Slice(hist.GetAxes()[0].GetNormalRange(1, 5)); + /// // The returned histogram will have 4 normal bins, an underflow and an overflow bin. + /// \endcode + /// + /// Slicing can also perform operations per dimension, see RSliceSpec. RSliceSpec::ROperationRebin allows to rebin + /// the histogram axis, grouping a number of normal bins into a new one: + /// \code + /// ROOT::Experimental::RHist hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto rebinned = hist.Slice(ROOT::Experimental::RSliceSpec::ROperationRebin(2)); + /// // The returned histogram has groups of two normal bins merged. + /// \endcode + /// + /// RSliceSpec::ROperationSum sums the bin contents along that axis, which allows to project to a lower-dimensional + /// histogram: + /// \code + /// ROOT::Experimental::RHist hist({/* two dimensions */}); + /// // Fill the histogram with a number of entries... + /// auto projected = hist.Slice(ROOT::Experimental::RSliceSpec{}, ROOT::Experimental::RSliceSpec::ROperationSum{}); + /// // The returned histogram has one dimension, with bin contents summed along the second axis. + /// \endcode + /// Note that it is not allowed to sum along all histogram axes because the return value would be a scalar. + /// + /// Ranges and operations can be combined. In that case, the range is applied before the operation. + /// + /// \warning Combining a range and the sum operation drops bin contents, which will taint the global histogram + /// statistics. Attempting to access its values, for example calling GetNEntries(), will throw exceptions. + /// + /// \param[in] args the arguments for each axis + /// \return the sliced histogram + /// \par See also + /// the \ref Slice(const std::vector &sliceSpecs) const "function overload" accepting `std::vector` + template + RHist Slice(const A &...args) const + { + std::vector sliceSpecs{args...}; + return Slice(sliceSpecs); + } + /// %ROOT Streamer function to throw when trying to store an object of this class. void Streamer(TBuffer &) { throw std::runtime_error("unable to store RHist"); } }; diff --git a/hist/histv7/inc/ROOT/RHistEngine.hxx b/hist/histv7/inc/ROOT/RHistEngine.hxx index abd37de3274cc..f04fd03304be8 100644 --- a/hist/histv7/inc/ROOT/RHistEngine.hxx +++ b/hist/histv7/inc/ROOT/RHistEngine.hxx @@ -12,6 +12,8 @@ #include "RHistUtils.hxx" #include "RLinearizedIndex.hxx" #include "RRegularAxis.hxx" +#include "RSliceBinIndexMapper.hxx" +#include "RSliceSpec.hxx" #include "RWeight.hxx" #include @@ -29,13 +31,9 @@ class TBuffer; namespace ROOT { namespace Experimental { -// forward declarations for friend declaration -template -class RHistEngine; -namespace Internal { -template -static void SetBinContent(RHistEngine &hist, const std::array &indices, const T &value); -} // namespace Internal +// forward declaration for friend declaration +template +class RHist; /** A histogram data structure to bin data along multiple dimensions. @@ -73,8 +71,8 @@ class RHistEngine final { template friend class RHistEngine; - template - friend void Internal::SetBinContent(RHistEngine &, const std::array &, const T &); + // For slicing, RHist needs to call SliceImpl. + friend class RHist; /// The axis configuration for this histogram. Relevant methods are forwarded from the public interface. Internal::RAxes fAxes; @@ -247,6 +245,78 @@ public: /// \return the multidimensional range RBinIndexMultiDimRange GetFullMultiDimRange() const { return fAxes.GetFullMultiDimRange(); } + /// Set the content of a single bin. + /// + /// \code + /// ROOT::Experimental::RHistEngine hist({/* two dimensions */}); + /// std::array indices = {3, 5}; + /// int value = /* ... */; + /// hist.SetBinContent(indices, value); + /// \endcode + /// + /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special + /// values. See also the class documentation of RBinIndex. + /// + /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found. + /// + /// \param[in] indices the array of indices for each axis + /// \param[in] value the new value of the bin content + /// \par See also + /// the \ref SetBinContent(const A &... args) const "variadic function template overload" accepting arguments + /// directly + template + void SetBinContent(const std::array &indices, const V &value) + { + // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might + // be confusing for users. + if (N != GetNDimensions()) { + throw std::invalid_argument("invalid number of indices passed to SetBinContent"); + } + RLinearizedIndex index = fAxes.ComputeGlobalIndex(indices); + if (!index.fValid) { + throw std::invalid_argument("bin not found in SetBinContent"); + } + assert(index.fIndex < fBinContents.size()); + // To allow conversion, we have to accept value with a template type V to capture any argument. Otherwise it would + // select the variadic function template... + fBinContents[index.fIndex] = value; + } + +private: + template + void SetBinContentImpl(const std::tuple &args, std::index_sequence) + { + std::array indices{std::get(args)...}; + SetBinContent(indices, std::get(args)); + } + +public: + /// Set the content of a single bin. + /// + /// \code + /// ROOT::Experimental::RHistEngine hist({/* two dimensions */}); + /// int value = /* ... */; + /// hist.SetBinContent(ROOT::Experimental::RBinIndex(3), ROOT::Experimental::RBinIndex(5), value); + /// // ... or construct the RBinIndex arguments implicitly from integers: + /// hist.SetBinContent(3, 5, value); + /// \endcode + /// + /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special + /// values. See also the class documentation of RBinIndex. + /// + /// Throws an exception if the number of arguments does not match the axis configuration or the bin is not found. + /// + /// \param[in] args the arguments for each axis and the new value of the bin content + /// \par See also + /// the \ref SetBinContent(const std::array &indices, const V &value) const "function overload" + /// accepting `std::array` + template + void SetBinContent(const A &...args) + { + auto t = std::forward_as_tuple(args...); + SetBinContentImpl(t, std::make_index_sequence()); + } + /// Add all bin contents of another histogram. /// /// Throws an exception if the axes configurations are not identical. @@ -578,24 +648,148 @@ public: } } +private: + RHistEngine SliceImpl(const std::vector &sliceSpecs, bool &dropped) const + { + if (sliceSpecs.size() != GetNDimensions()) { + throw std::invalid_argument("invalid number of specifications passed to Slice"); + } + + // Slice the axes. + std::vector axes; + for (std::size_t i = 0; i < sliceSpecs.size(); i++) { + // A sum operation makes the dimension disappear. + if (sliceSpecs[i].GetOperationSum() == nullptr) { + axes.push_back(fAxes.Get()[i].Slice(sliceSpecs[i])); + } + } + if (axes.empty()) { + throw std::invalid_argument("summing across all dimensions is not supported"); + } + + RHistEngine sliced(std::move(axes)); + + // Create the helper objects to map the bin contents to the sliced histogram. + Internal::RSliceBinIndexMapper mapper(sliceSpecs); + assert(mapper.GetMappedDimensionality() == sliced.GetNDimensions()); + std::vector mappedIndices(mapper.GetMappedDimensionality()); + + auto origRange = fAxes.GetFullMultiDimRange(); + auto origRangeIt = origRange.begin(); + + for (std::size_t i = 0; i < fBinContents.size(); i++) { + const auto &origIndices = *origRangeIt; +#ifndef NDEBUG + // Verify that the original indices correspond to the iteration variable. + RLinearizedIndex origIndex = fAxes.ComputeGlobalIndex(origIndices); + assert(origIndex.fValid); + assert(origIndex.fIndex == i); +#endif + + bool success = mapper.Map(origIndices, mappedIndices); + if (success) { + RLinearizedIndex mappedIndex = sliced.fAxes.ComputeGlobalIndex(mappedIndices); + assert(mappedIndex.fValid); + sliced.fBinContents[mappedIndex.fIndex] += fBinContents[i]; + } else { + dropped = true; + } + ++origRangeIt; + } + + return sliced; + } + +public: + /// Slice this histogram with an RSliceSpec per dimension. + /// + /// With a range, only the specified bins are retained. All other bin contents are transferred to the underflow and + /// overflow bins: + /// \code + /// ROOT::Experimental::RHistEngine hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto sliced = hist.Slice({hist.GetAxes()[0].GetNormalRange(1, 5)}); + /// // The returned histogram will have 4 normal bins, an underflow and an overflow bin. + /// \endcode + /// + /// Slicing can also perform operations per dimension, see RSliceSpec. RSliceSpec::ROperationRebin allows to rebin + /// the histogram axis, grouping a number of normal bins into a new one: + /// \code + /// ROOT::Experimental::RHistEngine hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto rebinned = hist.Slice(ROOT::Experimental::RSliceSpec::ROperationRebin(2)); + /// // The returned histogram has groups of two normal bins merged. + /// \endcode + /// + /// RSliceSpec::ROperationSum sums the bin contents along that axis, which allows to project to a lower-dimensional + /// histogram: + /// \code + /// ROOT::Experimental::RHistEngine hist({/* two dimensions */}); + /// // Fill the histogram with a number of entries... + /// auto projected = hist.Slice(ROOT::Experimental::RSliceSpec{}, ROOT::Experimental::RSliceSpec::ROperationSum{}); + /// // The returned histogram has one dimension, with bin contents summed along the second axis. + /// \endcode + /// Note that it is not allowed to sum along all histogram axes because the return value would be a scalar. + /// + /// Ranges and operations can be combined. In that case, the range is applied before the operation. + /// + /// \param[in] sliceSpecs the slice specifications for each axis + /// \return the sliced histogram + /// \par See also + /// the \ref Slice(const A &... args) const "variadic function template overload" accepting arguments directly + RHistEngine Slice(const std::vector &sliceSpecs) const + { + bool dropped = false; + return SliceImpl(sliceSpecs, dropped); + } + + /// Slice this histogram with an RSliceSpec per dimension. + /// + /// With a range, only the specified bins are retained. All other bin contents are transferred to the underflow and + /// overflow bins: + /// \code + /// ROOT::Experimental::RHistEngine hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto sliced = hist.Slice(hist.GetAxes()[0].GetNormalRange(1, 5)); + /// // The returned histogram will have 4 normal bins, an underflow and an overflow bin. + /// \endcode + /// + /// Slicing can also perform operations per dimension, see RSliceSpec. RSliceSpec::ROperationRebin allows to rebin + /// the histogram axis, grouping a number of normal bins into a new one: + /// \code + /// ROOT::Experimental::RHistEngine hist(/* one dimension */); + /// // Fill the histogram with a number of entries... + /// auto rebinned = hist.Slice(ROOT::Experimental::RSliceSpec::ROperationRebin(2)); + /// // The returned histogram has groups of two normal bins merged. + /// \endcode + /// + /// RSliceSpec::ROperationSum sums the bin contents along that axis, which allows to project to a lower-dimensional + /// histogram: + /// \code + /// ROOT::Experimental::RHistEngine hist({/* two dimensions */}); + /// // Fill the histogram with a number of entries... + /// auto projected = hist.Slice(ROOT::Experimental::RSliceSpec{}, ROOT::Experimental::RSliceSpec::ROperationSum{}); + /// // The returned histogram has one dimension, with bin contents summed along the second axis. + /// \endcode + /// Note that it is not allowed to sum along all histogram axes because the return value would be a scalar. + /// + /// Ranges and operations can be combined. In that case, the range is applied before the operation. + /// + /// \param[in] args the arguments for each axis + /// \return the sliced histogram + /// \par See also + /// the \ref Slice(const std::vector &sliceSpecs) const "function overload" accepting `std::vector` + template + RHistEngine Slice(const A &...args) const + { + std::vector sliceSpecs{args...}; + return Slice(sliceSpecs); + } + /// %ROOT Streamer function to throw when trying to store an object of this class. void Streamer(TBuffer &) { throw std::runtime_error("unable to store RHistEngine"); } }; -namespace Internal { -/// %Internal function to set the content of a single bin. -template -static void SetBinContent(RHistEngine &hist, const std::array &indices, const T &value) -{ - RLinearizedIndex index = hist.fAxes.ComputeGlobalIndex(indices); - if (!index.fValid) { - throw std::invalid_argument("bin not found in SetBinContent"); - } - assert(index.fIndex < hist.fBinContents.size()); - hist.fBinContents[index.fIndex] = value; -} -} // namespace Internal - } // namespace Experimental } // namespace ROOT diff --git a/hist/histv7/inc/ROOT/RHistStats.hxx b/hist/histv7/inc/ROOT/RHistStats.hxx index 462de88082aeb..fad20f9054777 100644 --- a/hist/histv7/inc/ROOT/RHistStats.hxx +++ b/hist/histv7/inc/ROOT/RHistStats.hxx @@ -23,6 +23,10 @@ class TBuffer; namespace ROOT { namespace Experimental { +// forward declaration for friend declaration +template +class RHist; + /** Histogram statistics of unbinned values. @@ -39,6 +43,9 @@ stats.Fill(1.5); Feedback is welcome! */ class RHistStats final { + template + friend class RHist; + public: /// Statistics for one dimension. struct RDimensionStats final { @@ -114,6 +121,16 @@ private: double fSumW2 = 0.0; /// The sums per dimension std::vector fDimensionStats; + /// Whether this object is tainted, in which case read access will throw. This is used if a user modifies bin + /// contents explicitly or slices histograms without preserving all entries, for example. + bool fTainted = false; + + void ThrowIfTainted() const + { + if (fTainted) { + throw std::logic_error("statistics are tainted, for example after setting bin contents or slicing"); + } + } public: /// Construct a statistics object. @@ -129,9 +146,21 @@ public: std::size_t GetNDimensions() const { return fDimensionStats.size(); } - std::uint64_t GetNEntries() const { return fNEntries; } - double GetSumW() const { return fSumW; } - double GetSumW2() const { return fSumW2; } + std::uint64_t GetNEntries() const + { + ThrowIfTainted(); + return fNEntries; + } + double GetSumW() const + { + ThrowIfTainted(); + return fSumW; + } + double GetSumW2() const + { + ThrowIfTainted(); + return fSumW2; + } /// Get the statistics object for one dimension. /// @@ -141,6 +170,8 @@ public: /// \return the statistics object const RDimensionStats &GetDimensionStats(std::size_t dim = 0) const { + ThrowIfTainted(); + const RDimensionStats &stats = fDimensionStats.at(dim); if (!stats.fEnabled) { throw std::invalid_argument("dimension is disabled"); @@ -157,6 +188,13 @@ public: bool IsEnabled(std::size_t dim) const { return fDimensionStats.at(dim).fEnabled; } + /// Taint this statistics object. + /// + /// It can still be filled, but any read access will throw until Clear() is called. + void Taint() { fTainted = true; } + + bool IsTainted() const { return fTainted; } + /// Add all entries from another statistics object. /// /// Throws an exception if the number of dimensions are not identical. @@ -164,20 +202,27 @@ public: /// \param[in] other another statistics object void Add(const RHistStats &other) { + // NB: this method does *not* call ThrowIfTainted() to allow adding RHist which may contain a tainted statistics + // object. if (fDimensionStats.size() != other.fDimensionStats.size()) { throw std::invalid_argument("number of dimensions not identical in Add"); } - fNEntries += other.fNEntries; - fSumW += other.fSumW; - fSumW2 += other.fSumW2; + // For exception safety, first check all dimensions before modifying the object. for (std::size_t i = 0; i < fDimensionStats.size(); i++) { if (fDimensionStats[i].fEnabled != other.fDimensionStats[i].fEnabled) { throw std::invalid_argument("the same dimensions must be enabled to combine statistics with Add"); } + } + + fNEntries += other.fNEntries; + fSumW += other.fSumW; + fSumW2 += other.fSumW2; + for (std::size_t i = 0; i < fDimensionStats.size(); i++) { if (fDimensionStats[i].fEnabled) { fDimensionStats[i].Add(other.fDimensionStats[i]); } } + fTainted |= other.fTainted; } /// Add all entries from another statistics object using atomic instructions. @@ -187,20 +232,27 @@ public: /// \param[in] other another statistics object that must not be modified during the operation void AddAtomic(const RHistStats &other) { + // NB: this method does *not* call ThrowIfTainted() to allow adding RHist which may contain a tainted statistics + // object. if (fDimensionStats.size() != other.fDimensionStats.size()) { - throw std::invalid_argument("number of dimensions not identical in Add"); + throw std::invalid_argument("number of dimensions not identical in AddAtomic"); } + // For exception safety, first check all dimensions before modifying the object. + for (std::size_t i = 0; i < fDimensionStats.size(); i++) { + if (fDimensionStats[i].fEnabled != other.fDimensionStats[i].fEnabled) { + throw std::invalid_argument("the same dimensions must be enabled to combine statistics with AddAtomic"); + } + } + Internal::AtomicAdd(&fNEntries, other.fNEntries); Internal::AtomicAdd(&fSumW, other.fSumW); Internal::AtomicAdd(&fSumW2, other.fSumW2); for (std::size_t i = 0; i < fDimensionStats.size(); i++) { - if (fDimensionStats[i].fEnabled != other.fDimensionStats[i].fEnabled) { - throw std::invalid_argument("the same dimensions must be enabled to combine statistics with Add"); - } if (fDimensionStats[i].fEnabled) { fDimensionStats[i].AddAtomic(other.fDimensionStats[i]); } } + fTainted |= other.fTainted; } /// Clear this statistics object. @@ -212,6 +264,7 @@ public: for (std::size_t i = 0; i < fDimensionStats.size(); i++) { fDimensionStats[i].Clear(); } + fTainted = false; } /// Compute the number of effective entries. @@ -223,6 +276,7 @@ public: /// \return the number of effective entries double ComputeNEffectiveEntries() const { + ThrowIfTainted(); if (fSumW2 == 0) { return std::numeric_limits::signaling_NaN(); } @@ -240,7 +294,7 @@ public: double ComputeMean(std::size_t dim = 0) const { // First get the statistics, which includes checking the argument. - auto &stats = fDimensionStats.at(dim); + auto &stats = GetDimensionStats(dim); if (fSumW == 0) { return std::numeric_limits::signaling_NaN(); } @@ -266,7 +320,7 @@ public: double ComputeVariance(std::size_t dim = 0) const { // First get the statistics, which includes checking the argument. - auto &stats = fDimensionStats.at(dim); + auto &stats = GetDimensionStats(dim); if (fSumW == 0) { return std::numeric_limits::signaling_NaN(); } @@ -310,7 +364,7 @@ public: double ComputeSkewness(std::size_t dim = 0) const { // First get the statistics, which includes checking the argument. - auto &stats = fDimensionStats.at(dim); + auto &stats = GetDimensionStats(dim); if (fSumW == 0) { return std::numeric_limits::signaling_NaN(); } @@ -347,7 +401,7 @@ public: double ComputeKurtosis(std::size_t dim = 0) const { // First get the statistics, which includes checking the argument. - auto &stats = fDimensionStats.at(dim); + auto &stats = GetDimensionStats(dim); if (fSumW == 0) { return std::numeric_limits::signaling_NaN(); } @@ -363,6 +417,20 @@ public: } private: + template + void CheckArguments(const std::tuple &args) const + { + using ArgumentType = std::tuple_element_t>; + if (fDimensionStats[I].fEnabled) { + if constexpr (!std::is_convertible_v) { + throw std::invalid_argument("invalid type of argument in RHistStats"); + } + } + if constexpr (I + 1 < N) { + CheckArguments(args); + } + } + template void FillImpl(const std::tuple &args) { @@ -371,7 +439,8 @@ private: if constexpr (std::is_convertible_v) { fDimensionStats[I].Add(std::get(args)); } else { - throw std::invalid_argument("invalid type of argument in RHistStats"); + // Should be checked in CheckArguments above! + assert(0); // GCOVR_EXCL_LINE } } if constexpr (I + 1 < sizeof...(A)) { @@ -389,7 +458,8 @@ private: } else { // Avoid compiler warning about unused parameter... (void)w; - throw std::invalid_argument("invalid type of argument in RHistStats"); + // Should be checked in CheckArguments above! + assert(0); // GCOVR_EXCL_LINE } } if constexpr (I + 1 < N) { @@ -418,6 +488,9 @@ public: if (sizeof...(A) != fDimensionStats.size()) { throw std::invalid_argument("invalid number of arguments to Fill"); } + // For exception safety, first check all arguments before modifying the object. + CheckArguments<0, sizeof...(A)>(args); + fNEntries++; fSumW++; fSumW2++; @@ -443,6 +516,9 @@ public: if (sizeof...(A) != fDimensionStats.size()) { throw std::invalid_argument("invalid number of arguments to Fill"); } + // For exception safety, first check all arguments before modifying the object. + CheckArguments<0, sizeof...(A)>(args); + fNEntries++; double w = weight.fValue; fSumW += w; @@ -479,6 +555,9 @@ public: if (N != fDimensionStats.size()) { throw std::invalid_argument("invalid number of arguments to Fill"); } + // For exception safety, first check all arguments before modifying the object. + CheckArguments<0, N>(t); + fNEntries++; double w = std::get(t).fValue; fSumW += w; @@ -495,6 +574,8 @@ public: /// \param[in] factor the scale factor void Scale(double factor) { + // NB: this method does *not* call ThrowIfTainted() to allow scaling RHist which may contain a tainted statistics + // object. fSumW *= factor; fSumW2 *= factor * factor; for (std::size_t i = 0; i < fDimensionStats.size(); i++) { diff --git a/hist/histv7/inc/ROOT/RRegularAxis.hxx b/hist/histv7/inc/ROOT/RRegularAxis.hxx index 67c27346063f5..449d5ff97a533 100644 --- a/hist/histv7/inc/ROOT/RRegularAxis.hxx +++ b/hist/histv7/inc/ROOT/RRegularAxis.hxx @@ -8,6 +8,7 @@ #include "RBinIndex.hxx" #include "RBinIndexRange.hxx" #include "RLinearizedIndex.hxx" +#include "RSliceSpec.hxx" #include #include @@ -83,6 +84,28 @@ public: double GetHigh() const { return fHigh; } bool HasFlowBins() const { return fEnableFlowBins; } + /// Compute the low edge of a bin. + /// + /// \param[in] bin the index, must be \f$< fNNormalBins\f$ + double ComputeLowEdge(std::uint64_t bin) const + { + if (bin >= fNNormalBins) { + throw std::invalid_argument("bin must be inside the axis"); + } + return fLow + (fHigh - fLow) * bin / fNNormalBins; + } + + /// Compute the high edge of a bin. + /// + /// \param[in] bin the index, must be \f$< fNNormalBins\f$ + double ComputeHighEdge(std::uint64_t bin) const + { + if (bin >= fNNormalBins) { + throw std::invalid_argument("bin must be inside the axis"); + } + return fLow + (fHigh - fLow) * (bin + 1) / fNNormalBins; + } + friend bool operator==(const RRegularAxis &lhs, const RRegularAxis &rhs) { return lhs.fNNormalBins == rhs.fNNormalBins && lhs.fLow == rhs.fLow && lhs.fHigh == rhs.fHigh && @@ -194,6 +217,59 @@ public: : GetNormalRange(); } + /// Slice this axis according to the specification. + /// + /// Throws an exception if the axis cannot be sliced: + /// * A sum operation makes the dimension disappear. + /// * The rebin operation must divide the number of normal bins. + /// + /// \param[in] sliceSpec the slice specification + /// \return the sliced axis, with enabled underflow and overflow bins + RRegularAxis Slice(const RSliceSpec &sliceSpec) const + { + if (sliceSpec.GetOperationSum() != nullptr) { + throw std::runtime_error("sum operation makes dimension disappear"); + } + + // Figure out the properties of the sliced axis. + std::uint64_t nNormalBins = fNNormalBins; + double low = fLow; + double high = fHigh; + + const auto &range = sliceSpec.GetRange(); + if (!range.IsInvalid()) { + std::uint64_t begin = 0; + std::uint64_t end = nNormalBins; + if (range.GetBegin().IsNormal()) { + begin = range.GetBegin().GetIndex(); + // Only compute a new lower end of the axis interval if needed. + if (begin > 0) { + low = ComputeLowEdge(begin); + } + } + if (range.GetEnd().IsNormal()) { + end = range.GetEnd().GetIndex(); + // Only compute a new upper end of the axis interval if needed, to avoid floating-point inaccuracies. + if (end < nNormalBins) { + high = ComputeHighEdge(end - 1); + } + } + nNormalBins = end - begin; + } + + if (auto *opRebin = sliceSpec.GetOperationRebin()) { + if (nNormalBins % opRebin->GetNGroup() != 0) { + throw std::runtime_error("rebin operation does not divide number of normal bins"); + } + nNormalBins /= opRebin->GetNGroup(); + } + + // The sliced axis always has flow bins enabled to preserve all entries. This is the least confusing for users, + // even if not always strictly necessary. + bool enableFlowBins = true; + return RRegularAxis(nNormalBins, {low, high}, enableFlowBins); + } + /// %ROOT Streamer function to throw when trying to store an object of this class. void Streamer(TBuffer &) { throw std::runtime_error("unable to store RRegularAxis"); } }; diff --git a/hist/histv7/inc/ROOT/RVariableBinAxis.hxx b/hist/histv7/inc/ROOT/RVariableBinAxis.hxx index 47e5f8970b2a2..58faa12ada28b 100644 --- a/hist/histv7/inc/ROOT/RVariableBinAxis.hxx +++ b/hist/histv7/inc/ROOT/RVariableBinAxis.hxx @@ -8,6 +8,7 @@ #include "RBinIndex.hxx" #include "RBinIndexRange.hxx" #include "RLinearizedIndex.hxx" +#include "RSliceSpec.hxx" #include #include @@ -196,6 +197,57 @@ public: : GetNormalRange(); } + /// Slice this axis according to the specification. + /// + /// Throws an exception if the axis cannot be sliced: + /// * A sum operation makes the dimension disappear. + /// * The rebin operation must divide the number of normal bins. + /// + /// \param[in] sliceSpec the slice specification + /// \return the sliced axis, with enabled underflow and overflow bins + RVariableBinAxis Slice(const RSliceSpec &sliceSpec) const + { + if (sliceSpec.GetOperationSum() != nullptr) { + throw std::runtime_error("sum operation makes dimension disappear"); + } + + // Figure out the properties of the sliced axis. + std::size_t nNormalBins = fBinEdges.size() - 1; + std::size_t begin = 0; + std::size_t end = nNormalBins; + + const auto &range = sliceSpec.GetRange(); + if (!range.IsInvalid()) { + if (range.GetBegin().IsNormal()) { + begin = range.GetBegin().GetIndex(); + } + if (range.GetEnd().IsNormal()) { + end = range.GetEnd().GetIndex(); + } + nNormalBins = end - begin; + } + + std::uint64_t nGroup = 1; + if (auto *opRebin = sliceSpec.GetOperationRebin()) { + nGroup = opRebin->GetNGroup(); + if (nNormalBins % nGroup != 0) { + throw std::runtime_error("rebin operation does not divide number of normal bins"); + } + } + + // Prepare the bin edges. + std::vector binEdges; + for (std::size_t bin = begin; bin < end; bin += nGroup) { + binEdges.push_back(fBinEdges[bin]); + } + binEdges.push_back(fBinEdges[end]); + + // The sliced axis always has flow bins enabled to preserve all entries. This is the least confusing for users, + // even if not always strictly necessary. + bool enableFlowBins = true; + return RVariableBinAxis(std::move(binEdges), enableFlowBins); + } + /// %ROOT Streamer function to throw when trying to store an object of this class. void Streamer(TBuffer &) { throw std::runtime_error("unable to store RVariableBinAxis"); } }; diff --git a/hist/histv7/test/hist_axis_variant.cxx b/hist/histv7/test/hist_axis_variant.cxx index 09c84923182eb..76f89accecae9 100644 --- a/hist/histv7/test/hist_axis_variant.cxx +++ b/hist/histv7/test/hist_axis_variant.cxx @@ -23,6 +23,11 @@ TEST(RAxisVariant, RegularAxis) EXPECT_EQ(std::distance(normal12.begin(), normal12.end()), 1); const auto full = axis.GetFullRange(); EXPECT_EQ(std::distance(full.begin(), full.end()), Bins + 2); + + const auto slicedAxis = axis.Slice(RSliceSpec{}); + EXPECT_EQ(slicedAxis.GetVariant().index(), 0); + EXPECT_TRUE(slicedAxis.GetRegularAxis() != nullptr); + EXPECT_EQ(slicedAxis.GetNNormalBins(), Bins); } { @@ -36,6 +41,11 @@ TEST(RAxisVariant, RegularAxis) EXPECT_EQ(std::distance(normal12.begin(), normal12.end()), 1); const auto full = axis.GetFullRange(); EXPECT_EQ(std::distance(full.begin(), full.end()), Bins); + + const auto slicedAxis = axis.Slice(RSliceSpec{}); + EXPECT_EQ(slicedAxis.GetVariant().index(), 0); + EXPECT_TRUE(slicedAxis.GetRegularAxis() != nullptr); + EXPECT_EQ(slicedAxis.GetNNormalBins(), Bins); } } @@ -64,6 +74,11 @@ TEST(RAxisVariant, VariableBinAxis) EXPECT_EQ(std::distance(normal12.begin(), normal12.end()), 1); const auto full = axis.GetFullRange(); EXPECT_EQ(std::distance(full.begin(), full.end()), Bins + 2); + + const auto slicedAxis = axis.Slice(RSliceSpec{}); + EXPECT_EQ(slicedAxis.GetVariant().index(), 1); + EXPECT_TRUE(slicedAxis.GetVariableBinAxis() != nullptr); + EXPECT_EQ(slicedAxis.GetNNormalBins(), Bins); } { @@ -77,6 +92,11 @@ TEST(RAxisVariant, VariableBinAxis) EXPECT_EQ(std::distance(normal12.begin(), normal12.end()), 1); const auto full = axis.GetFullRange(); EXPECT_EQ(std::distance(full.begin(), full.end()), Bins); + + const auto slicedAxis = axis.Slice(RSliceSpec{}); + EXPECT_EQ(slicedAxis.GetVariant().index(), 1); + EXPECT_TRUE(slicedAxis.GetVariableBinAxis() != nullptr); + EXPECT_EQ(slicedAxis.GetNNormalBins(), Bins); } } @@ -100,6 +120,11 @@ TEST(RAxisVariant, CategoricalAxis) EXPECT_EQ(std::distance(normal12.begin(), normal12.end()), 1); const auto full = axis.GetFullRange(); EXPECT_EQ(std::distance(full.begin(), full.end()), 4); + + const auto slicedAxis = axis.Slice(RSliceSpec{}); + EXPECT_EQ(slicedAxis.GetVariant().index(), 2); + EXPECT_TRUE(slicedAxis.GetCategoricalAxis() != nullptr); + EXPECT_EQ(slicedAxis.GetNNormalBins(), 3); } { @@ -113,5 +138,10 @@ TEST(RAxisVariant, CategoricalAxis) EXPECT_EQ(std::distance(normal12.begin(), normal12.end()), 1); const auto full = axis.GetFullRange(); EXPECT_EQ(std::distance(full.begin(), full.end()), 3); + + const auto slicedAxis = axis.Slice(RSliceSpec{}); + EXPECT_EQ(slicedAxis.GetVariant().index(), 2); + EXPECT_TRUE(slicedAxis.GetCategoricalAxis() != nullptr); + EXPECT_EQ(slicedAxis.GetNNormalBins(), 3); } } diff --git a/hist/histv7/test/hist_categorical.cxx b/hist/histv7/test/hist_categorical.cxx index ef9f5269932b9..a5ecd4d2646d2 100644 --- a/hist/histv7/test/hist_categorical.cxx +++ b/hist/histv7/test/hist_categorical.cxx @@ -198,3 +198,35 @@ TEST(RCategoricalAxis, GetFullRange) EXPECT_EQ(std::distance(full.begin(), full.end()), categories.size()); } } + +static void Test_RCategoricalAxis_Slice(bool enableOverflowBin) +{ + const std::vector categories = {"a", "b", "c"}; + const RCategoricalAxis origAxis(categories, enableOverflowBin); + ASSERT_EQ(origAxis.HasOverflowBin(), enableOverflowBin); + + { + // The only allowed "slicing" is to keep the entire axis. + const RSliceSpec full; + const auto axis = origAxis.Slice(full); + EXPECT_EQ(axis.GetNNormalBins(), 3); + EXPECT_EQ(axis.GetCategories(), categories); + EXPECT_TRUE(axis.HasOverflowBin()); + } + + // Slicing and other operations are not allowed / implemented. + EXPECT_THROW(origAxis.Slice(origAxis.GetFullRange()), std::runtime_error); + EXPECT_THROW(origAxis.Slice(origAxis.GetNormalRange()), std::runtime_error); + EXPECT_THROW(origAxis.Slice(RSliceSpec::ROperationRebin(2)), std::runtime_error); + EXPECT_THROW(origAxis.Slice(RSliceSpec::ROperationSum{}), std::runtime_error); +} + +TEST(RCategoricalAxis, Slice) +{ + Test_RCategoricalAxis_Slice(true); +} + +TEST(RCategoricalAxis, SliceNoOverflowBin) +{ + Test_RCategoricalAxis_Slice(false); +} diff --git a/hist/histv7/test/hist_engine.cxx b/hist/histv7/test/hist_engine.cxx index bc2ae778f3a7c..e606e3ecc60a3 100644 --- a/hist/histv7/test/hist_engine.cxx +++ b/hist/histv7/test/hist_engine.cxx @@ -132,19 +132,51 @@ TEST(RHistEngine, GetFullMultiDimRange) TEST(RHistEngine, SetBinContent) { - using ROOT::Experimental::Internal::SetBinContent; - static constexpr std::size_t Bins = 20; const RRegularAxis axis(Bins, {0, Bins}); RHistEngine engine({axis}); - std::array indices = {7}; - SetBinContent(engine, indices, 42); - EXPECT_EQ(engine.GetBinContent(indices), 42); + const RBinIndex index(7); + engine.SetBinContent(index, 42); + EXPECT_EQ(engine.GetBinContent(index), 42); + + const std::array indices = {index}; + engine.SetBinContent(indices, 43); + EXPECT_EQ(engine.GetBinContent(indices), 43); - // "bin not found" - indices = {Bins}; - EXPECT_THROW(SetBinContent(engine, indices, 43), std::invalid_argument); + // This also works if the value must be converted to the bin content type. + RHistEngine engineF({axis}); + engineF.SetBinContent(index, 42); + EXPECT_EQ(engineF.GetBinContent(index), 42); + + engineF.SetBinContent(indices, 43); + EXPECT_EQ(engineF.GetBinContent(indices), 43); +} + +TEST(RHistEngine, SetBinContentInvalidNumberOfArguments) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine1({axis}); + ASSERT_EQ(engine1.GetNDimensions(), 1); + RHistEngine engine2({axis, axis}); + ASSERT_EQ(engine2.GetNDimensions(), 2); + + EXPECT_NO_THROW(engine1.SetBinContent(1, 0)); + EXPECT_THROW(engine1.SetBinContent(1, 2, 0), std::invalid_argument); + + EXPECT_THROW(engine2.SetBinContent(1, 0), std::invalid_argument); + EXPECT_NO_THROW(engine2.SetBinContent(1, 2, 0)); + EXPECT_THROW(engine2.SetBinContent(1, 2, 3, 0), std::invalid_argument); +} + +TEST(RHistEngine, SetBinContentNotFound) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine({axis}); + + EXPECT_THROW(engine.SetBinContent(Bins, 0), std::invalid_argument); } TEST(RHistEngine, Add) @@ -447,6 +479,19 @@ TEST(RHistEngine, FillTupleWeightInvalidNumberOfArguments) EXPECT_THROW(engine2.Fill(std::make_tuple(1, 2, 3), RWeight(1)), std::invalid_argument); } +TEST(RHistEngine, FillWeightNegative) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine({axis}); + + engine.Fill(1.5, RWeight(1)); + ASSERT_EQ(engine.GetBinContent(RBinIndex(1)), 1); + + engine.Fill(1.5, RWeight(-1)); + EXPECT_EQ(engine.GetBinContent(RBinIndex(1)), 0); +} + TEST(RHistEngine, Scale) { static constexpr std::size_t Bins = 20; diff --git a/hist/histv7/test/hist_hist.cxx b/hist/histv7/test/hist_hist.cxx index 2b03b4f7fa4db..2cc6d2190f2cf 100644 --- a/hist/histv7/test/hist_hist.cxx +++ b/hist/histv7/test/hist_hist.cxx @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,31 @@ TEST(RHist, GetFullMultiDimRange) EXPECT_FLOAT_EQ(hist.GetStats().GetSumW(), sumW); } +TEST(RHist, SetBinContent) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + + { + RHist hist(axis); + ASSERT_FALSE(hist.GetStats().IsTainted()); + hist.SetBinContent(RBinIndex(1), 42); + EXPECT_EQ(hist.GetBinContent(RBinIndex(1)), 42); + EXPECT_TRUE(hist.GetStats().IsTainted()); + EXPECT_THROW(hist.GetNEntries(), std::logic_error); + } + + { + RHist hist(axis); + ASSERT_FALSE(hist.GetStats().IsTainted()); + const std::array indices = {2}; + hist.SetBinContent(indices, 42); + EXPECT_EQ(hist.GetBinContent(indices), 42); + EXPECT_TRUE(hist.GetStats().IsTainted()); + EXPECT_THROW(hist.GetNEntries(), std::logic_error); + } +} + TEST(RHist, Add) { static constexpr std::size_t Bins = 20; @@ -139,6 +165,33 @@ TEST(RHist, StressAddAtomic) EXPECT_EQ(histA.GetBinContent(0), NAdds); } +TEST(RHist, AddExceptionSafety) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis regularAxis(Bins, {0, Bins}); + const std::vector categories = {"a", "b", "c"}; + const RCategoricalAxis categoricalAxis(categories); + + RHist histA({regularAxis, regularAxis}); + RHist histB({regularAxis, categoricalAxis}); + + histA.Fill(1.5, 2.5); + ASSERT_EQ(histA.GetNEntries(), 1); + ASSERT_EQ(histA.GetBinContent(RBinIndex(1), RBinIndex(2)), 1); + histB.Fill(1.5, "b"); + + EXPECT_THROW(histA.Add(histB), std::invalid_argument); + EXPECT_THROW(histA.AddAtomic(histB), std::invalid_argument); + + // Verify exception safety. Only the original entry should be there. + EXPECT_EQ(histA.GetNEntries(), 1); + EXPECT_EQ(histA.GetBinContent(RBinIndex(1), RBinIndex(2)), 1); + EXPECT_EQ(histA.GetStats().GetSumW(), 1); + EXPECT_EQ(histA.GetStats().GetSumW2(), 1); + EXPECT_EQ(histA.GetStats().GetDimensionStats(0).fSumWX, 1.5); + EXPECT_EQ(histA.GetStats().GetDimensionStats(1).fSumWX, 2.5); +} + TEST(RHist, Clear) { static constexpr std::size_t Bins = 20; @@ -273,6 +326,30 @@ TEST(RHist, FillCategoricalWeight) EXPECT_FLOAT_EQ(hist.ComputeNEffectiveEntries(), 1.9931034); } +TEST(RHist, FillExceptionSafety) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist({axis, axis}); + + hist.Fill(1.5, 2.5); + ASSERT_EQ(hist.GetNEntries(), 1); + ASSERT_EQ(hist.GetBinContent(RBinIndex(1), RBinIndex(2)), 1); + + EXPECT_THROW(hist.Fill(1.5, "b"), std::invalid_argument); + EXPECT_THROW(hist.Fill(std::make_tuple(1.5, "b")), std::invalid_argument); + EXPECT_THROW(hist.Fill(1.5, "b", RWeight(1)), std::invalid_argument); + EXPECT_THROW(hist.Fill(std::make_tuple(1.5, "b"), RWeight(1)), std::invalid_argument); + + // Verify exception safety. Only the first entry should be there. + EXPECT_EQ(hist.GetNEntries(), 1); + EXPECT_EQ(hist.GetBinContent(RBinIndex(1), RBinIndex(2)), 1); + EXPECT_EQ(hist.GetStats().GetSumW(), 1); + EXPECT_EQ(hist.GetStats().GetSumW2(), 1); + EXPECT_EQ(hist.GetStats().GetDimensionStats(0).fSumWX, 1.5); + EXPECT_EQ(hist.GetStats().GetDimensionStats(1).fSumWX, 2.5); +} + TEST(RHist, Scale) { static constexpr std::size_t Bins = 20; diff --git a/hist/histv7/test/hist_regular.cxx b/hist/histv7/test/hist_regular.cxx index 8b4793af912a9..58917956796ec 100644 --- a/hist/histv7/test/hist_regular.cxx +++ b/hist/histv7/test/hist_regular.cxx @@ -32,6 +32,20 @@ TEST(RRegularAxis, Constructor) EXPECT_THROW(RRegularAxis(Bins, {0, NaN}), std::invalid_argument); } +TEST(RRegularAxis, ComputeLowHighEdge) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + + for (std::size_t i = 0; i < Bins; i++) { + EXPECT_EQ(axis.ComputeLowEdge(i), i); + EXPECT_EQ(axis.ComputeHighEdge(i), i + 1); + } + + EXPECT_THROW(axis.ComputeLowEdge(Bins), std::invalid_argument); + EXPECT_THROW(axis.ComputeHighEdge(Bins), std::invalid_argument); +} + TEST(RRegularAxis, Equality) { static constexpr std::size_t Bins = 20; @@ -258,3 +272,62 @@ TEST(RRegularAxis, GetFullRange) EXPECT_EQ(std::distance(full.begin(), full.end()), Bins); } } + +static void Test_RegularAxis_Slice(bool enableFlowBins) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis origAxis(Bins, {0, Bins}, enableFlowBins); + ASSERT_EQ(origAxis.HasFlowBins(), enableFlowBins); + + // Three different ways of "slicing" which will keep the entire axis. + for (auto sliceSpec : {RSliceSpec{}, RSliceSpec(origAxis.GetFullRange()), RSliceSpec(origAxis.GetNormalRange())}) { + const auto axis = origAxis.Slice(sliceSpec); + EXPECT_EQ(axis.GetNNormalBins(), Bins); + EXPECT_EQ(axis.GetLow(), 0); + EXPECT_EQ(axis.GetHigh(), Bins); + EXPECT_TRUE(axis.HasFlowBins()); + } + + { + const RSliceSpec slice(origAxis.GetNormalRange(1, Bins - 1)); + const auto axis = origAxis.Slice(slice); + EXPECT_EQ(axis.GetNNormalBins(), Bins - 2); + EXPECT_EQ(axis.GetLow(), 1); + EXPECT_EQ(axis.GetHigh(), Bins - 1); + EXPECT_TRUE(axis.HasFlowBins()); + } + + { + const RSliceSpec rebin(RSliceSpec::ROperationRebin(2)); + const auto axis = origAxis.Slice(rebin); + EXPECT_EQ(axis.GetNNormalBins(), Bins / 2); + EXPECT_EQ(axis.GetLow(), 0); + EXPECT_EQ(axis.GetHigh(), Bins); + EXPECT_TRUE(axis.HasFlowBins()); + } + + // Rebin grouping must divide the number of normal bins. + EXPECT_THROW(origAxis.Slice(RSliceSpec::ROperationRebin(3)), std::runtime_error); + + // Sum operation makes dimension disappear. + EXPECT_THROW(origAxis.Slice(RSliceSpec::ROperationSum{}), std::runtime_error); + + { + const RSliceSpec sliceRebin(origAxis.GetNormalRange(1, 5), RSliceSpec::ROperationRebin(2)); + const auto axis = origAxis.Slice(sliceRebin); + EXPECT_EQ(axis.GetNNormalBins(), 2); + EXPECT_EQ(axis.GetLow(), 1); + EXPECT_EQ(axis.GetHigh(), 5); + EXPECT_TRUE(axis.HasFlowBins()); + } +} + +TEST(RRegularAxis, Slice) +{ + Test_RegularAxis_Slice(true); +} + +TEST(RRegularAxis, SliceNoFlowBins) +{ + Test_RegularAxis_Slice(false); +} diff --git a/hist/histv7/test/hist_slice.cxx b/hist/histv7/test/hist_slice.cxx index 3df462cbb9433..5805e49d201bc 100644 --- a/hist/histv7/test/hist_slice.cxx +++ b/hist/histv7/test/hist_slice.cxx @@ -285,3 +285,344 @@ TEST(RSliceBinIndexMapper, MapSliceFullSum) EXPECT_TRUE(success); } } + +TEST(RHistEngine, SliceInvalidNumberOfArguments) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + const RHistEngine engine1(axis); + ASSERT_EQ(engine1.GetNDimensions(), 1); + const RHistEngine engine2(axis, axis); + ASSERT_EQ(engine2.GetNDimensions(), 2); + + EXPECT_NO_THROW(engine1.Slice(RSliceSpec{})); + EXPECT_THROW(engine1.Slice(RSliceSpec{}, RSliceSpec{}), std::invalid_argument); + + EXPECT_THROW(engine2.Slice(RSliceSpec{}), std::invalid_argument); + EXPECT_NO_THROW(engine2.Slice(RSliceSpec{}, RSliceSpec{})); + EXPECT_THROW(engine2.Slice(RSliceSpec{}, RSliceSpec{}, RSliceSpec{}), std::invalid_argument); +} + +TEST(RHistEngine, SliceSumAll) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + const RHistEngine engine1(axis); + ASSERT_EQ(engine1.GetNDimensions(), 1); + const RHistEngine engine2(axis, axis); + ASSERT_EQ(engine2.GetNDimensions(), 2); + + const RSliceSpec sum(RSliceSpec::ROperationSum{}); + EXPECT_THROW(engine1.Slice(sum), std::invalid_argument); + EXPECT_THROW(engine2.Slice(sum, sum), std::invalid_argument); +} + +TEST(RHistEngine, SliceFull) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine(axis); + + engine.SetBinContent(RBinIndex::Underflow(), 100); + for (std::size_t i = 0; i < Bins; i++) { + engine.SetBinContent(i, i + 1); + } + engine.SetBinContent(RBinIndex::Overflow(), 200); + + // Three different ways of "slicing" which will keep the entire axis. + for (auto sliceSpec : {RSliceSpec{}, RSliceSpec(axis.GetFullRange()), RSliceSpec(axis.GetNormalRange())}) { + const auto sliced = engine.Slice(sliceSpec); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_TRUE(sliced.GetAxes()[0].GetRegularAxis() != nullptr); + EXPECT_EQ(sliced.GetAxes()[0].GetNNormalBins(), Bins); + EXPECT_EQ(sliced.GetTotalNBins(), Bins + 2); + + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Underflow()), 100); + for (std::size_t i = 0; i < Bins; i++) { + EXPECT_EQ(sliced.GetBinContent(i), i + 1); + } + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Overflow()), 200); + } +} + +TEST(RHistEngine, SliceNormal) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine(axis); + + engine.SetBinContent(RBinIndex::Underflow(), 100); + for (std::size_t i = 0; i < Bins; i++) { + engine.SetBinContent(i, i + 1); + } + engine.SetBinContent(RBinIndex::Overflow(), 200); + + const auto sliced = engine.Slice(axis.GetNormalRange(1, 5)); + ASSERT_EQ(sliced.GetNDimensions(), 1); + const auto *regular = sliced.GetAxes()[0].GetRegularAxis(); + ASSERT_TRUE(regular != nullptr); + EXPECT_EQ(regular->GetNNormalBins(), 4); + EXPECT_EQ(regular->GetLow(), 1); + EXPECT_EQ(regular->GetHigh(), 5); + EXPECT_EQ(sliced.GetTotalNBins(), 6); + + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Underflow()), 101); + for (std::size_t i = 0; i < 4; i++) { + EXPECT_EQ(sliced.GetBinContent(i), i + 2); + } + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Overflow()), 395); +} + +TEST(RHistEngine, SliceRebin) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine(axis); + + engine.SetBinContent(RBinIndex::Underflow(), 100); + for (std::size_t i = 0; i < Bins; i++) { + engine.SetBinContent(i, i + 1); + } + engine.SetBinContent(RBinIndex::Overflow(), 200); + + const auto sliced = engine.Slice(RSliceSpec::ROperationRebin(2)); + ASSERT_EQ(sliced.GetNDimensions(), 1); + const auto *regular = sliced.GetAxes()[0].GetRegularAxis(); + ASSERT_TRUE(regular != nullptr); + EXPECT_EQ(regular->GetNNormalBins(), Bins / 2); + EXPECT_EQ(regular->GetLow(), 0); + EXPECT_EQ(regular->GetHigh(), Bins); + EXPECT_EQ(sliced.GetTotalNBins(), Bins / 2 + 2); + + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Underflow()), 100); + for (std::size_t i = 0; i < Bins / 2; i++) { + EXPECT_EQ(sliced.GetBinContent(i), 4 * i + 3); + } + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Overflow()), 200); +} + +TEST(RHistEngine, SliceRangeRebin) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine(axis); + + engine.SetBinContent(RBinIndex::Underflow(), 100); + for (std::size_t i = 0; i < Bins; i++) { + engine.SetBinContent(i, i + 1); + } + engine.SetBinContent(RBinIndex::Overflow(), 200); + + const RSliceSpec spec(axis.GetNormalRange(1, 5), RSliceSpec::ROperationRebin(2)); + const auto sliced = engine.Slice(spec); + ASSERT_EQ(sliced.GetNDimensions(), 1); + const auto *regular = sliced.GetAxes()[0].GetRegularAxis(); + ASSERT_TRUE(regular != nullptr); + EXPECT_EQ(regular->GetNNormalBins(), 2); + EXPECT_EQ(regular->GetLow(), 1); + EXPECT_EQ(regular->GetHigh(), 5); + EXPECT_EQ(sliced.GetTotalNBins(), 4); + + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Underflow()), 101); + for (std::size_t i = 0; i < 2; i++) { + EXPECT_EQ(sliced.GetBinContent(i), 4 * i + 5); + } + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Overflow()), 395); +} + +TEST(RHistEngine, SliceSum) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine(axis, axis); + + engine.SetBinContent(RBinIndex::Underflow(), 0, 1000); + engine.SetBinContent(RBinIndex::Underflow(), 2, 2000); + for (std::size_t i = 0; i < Bins; i++) { + for (std::size_t j = 0; j < Bins; j++) { + engine.SetBinContent(i, RBinIndex::Underflow(), 100 * i); + engine.SetBinContent(i, RBinIndex(j), i * Bins + j); + engine.SetBinContent(i, RBinIndex::Overflow(), 200 * i); + } + } + engine.SetBinContent(RBinIndex::Overflow(), 3, 3000); + engine.SetBinContent(RBinIndex::Overflow(), 6, 4000); + + const auto sliced = engine.Slice(RSliceSpec{}, RSliceSpec::ROperationSum{}); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_TRUE(sliced.GetAxes()[0].GetRegularAxis() != nullptr); + EXPECT_EQ(sliced.GetAxes()[0].GetNNormalBins(), Bins); + EXPECT_EQ(sliced.GetTotalNBins(), Bins + 2); + + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Underflow()), 3000); + for (std::size_t i = 0; i < Bins; i++) { + EXPECT_EQ(sliced.GetBinContent(i), i * (100 + Bins * Bins + 200) + Bins * (Bins - 1) / 2); + } + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Overflow()), 7000); +} + +TEST(RHistEngine, SliceRangeSum) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine(axis, axis); + + engine.SetBinContent(RBinIndex::Underflow(), 0, 1000); + engine.SetBinContent(RBinIndex::Underflow(), 2, 2000); + for (std::size_t i = 0; i < Bins; i++) { + for (std::size_t j = 0; j < Bins; j++) { + engine.SetBinContent(i, RBinIndex::Underflow(), 100 * i); + engine.SetBinContent(i, RBinIndex(j), i * Bins + j); + engine.SetBinContent(i, RBinIndex::Overflow(), 200 * i); + } + } + engine.SetBinContent(RBinIndex::Overflow(), 3, 3000); + engine.SetBinContent(RBinIndex::Overflow(), 6, 4000); + + const RSliceSpec rangeSum(axis.GetNormalRange(1, 5), RSliceSpec::ROperationSum{}); + const auto sliced = engine.Slice(RSliceSpec{}, rangeSum); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_TRUE(sliced.GetAxes()[0].GetRegularAxis() != nullptr); + EXPECT_EQ(sliced.GetAxes()[0].GetNNormalBins(), Bins); + EXPECT_EQ(sliced.GetTotalNBins(), Bins + 2); + + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Underflow()), 2000); + for (std::size_t i = 0; i < Bins; i++) { + EXPECT_EQ(sliced.GetBinContent(i), 4 * i * Bins + 10); + } + EXPECT_EQ(sliced.GetBinContent(RBinIndex::Overflow()), 3000); +} + +TEST(RHist, SliceTainted) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis); + + hist.SetBinContent(RBinIndex(1), 2); + ASSERT_TRUE(hist.GetStats().IsTainted()); + + const auto sliced = hist.Slice(RSliceSpec{}); + EXPECT_TRUE(sliced.GetStats().IsTainted()); +} + +TEST(RHist, SliceFull) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis); + + hist.Fill(1.5); + ASSERT_EQ(hist.GetNEntries(), 1); + + // Three different ways of "slicing" which will keep the entire axis. + for (auto sliceSpec : {RSliceSpec{}, RSliceSpec(axis.GetFullRange()), RSliceSpec(axis.GetNormalRange())}) { + const auto sliced = hist.Slice(sliceSpec); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_EQ(sliced.GetTotalNBins(), Bins + 2); + + EXPECT_FALSE(sliced.GetStats().IsTainted()); + EXPECT_EQ(sliced.GetBinContent(1), 1); + } +} + +TEST(RHist, SliceNormal) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis); + + hist.Fill(1.5); + ASSERT_EQ(hist.GetNEntries(), 1); + + const auto sliced = hist.Slice(axis.GetNormalRange(1, 5)); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_EQ(sliced.GetTotalNBins(), 6); + EXPECT_EQ(sliced.GetBinContent(0), 1); + + // The sliced histogram still has the same statistics. + EXPECT_FALSE(sliced.GetStats().IsTainted()); + EXPECT_EQ(sliced.GetNEntries(), 1); + EXPECT_EQ(sliced.ComputeMean(), 1.5); +} + +TEST(RHist, SliceRebin) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis); + + hist.Fill(1.5); + ASSERT_EQ(hist.GetNEntries(), 1); + + const auto sliced = hist.Slice(RSliceSpec::ROperationRebin(2)); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_EQ(sliced.GetTotalNBins(), Bins / 2 + 2); + EXPECT_EQ(sliced.GetBinContent(0), 1); + + // The sliced histogram still has the same statistics. + EXPECT_FALSE(sliced.GetStats().IsTainted()); + EXPECT_EQ(sliced.GetNEntries(), 1); + EXPECT_EQ(sliced.ComputeMean(), 1.5); +} + +TEST(RHist, SliceRangeRebin) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis); + + hist.Fill(1.5); + ASSERT_EQ(hist.GetNEntries(), 1); + + const RSliceSpec spec(axis.GetNormalRange(1, 5), RSliceSpec::ROperationRebin(2)); + const auto sliced = hist.Slice(spec); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_EQ(sliced.GetTotalNBins(), 4); + EXPECT_EQ(sliced.GetBinContent(0), 1); + + // The sliced histogram still has the same statistics. + EXPECT_FALSE(sliced.GetStats().IsTainted()); + EXPECT_EQ(sliced.GetNEntries(), 1); + EXPECT_EQ(sliced.ComputeMean(), 1.5); +} + +TEST(RHist, SliceSum) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis, axis); + + hist.Fill(1.5, 2.5); + ASSERT_EQ(hist.GetNEntries(), 1); + + const auto sliced = hist.Slice(RSliceSpec{}, RSliceSpec::ROperationSum{}); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_EQ(sliced.GetTotalNBins(), Bins + 2); + EXPECT_EQ(sliced.GetBinContent(1), 1); + + // The first dimension still has the same statistics. + EXPECT_FALSE(sliced.GetStats().IsTainted()); + EXPECT_EQ(sliced.GetNEntries(), 1); + EXPECT_EQ(sliced.ComputeMean(), 1.5); +} + +TEST(RHist, SliceRangeSum) +{ + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHist hist(axis, axis); + + hist.Fill(1.5, 2.5); + ASSERT_EQ(hist.GetNEntries(), 1); + + const RSliceSpec rangeSum(axis.GetNormalRange(1, 5), RSliceSpec::ROperationSum{}); + const auto sliced = hist.Slice(RSliceSpec{}, rangeSum); + ASSERT_EQ(sliced.GetNDimensions(), 1); + EXPECT_EQ(sliced.GetTotalNBins(), Bins + 2); + EXPECT_EQ(sliced.GetBinContent(1), 1); + + // The slicing could have dropped entries (even if it didn't in this case), the statistics are tainted. + EXPECT_TRUE(sliced.GetStats().IsTainted()); + EXPECT_THROW(sliced.GetNEntries(), std::logic_error); +} diff --git a/hist/histv7/test/hist_stats.cxx b/hist/histv7/test/hist_stats.cxx index 1b1f9542fb92a..5748490ddf4bc 100644 --- a/hist/histv7/test/hist_stats.cxx +++ b/hist/histv7/test/hist_stats.cxx @@ -98,6 +98,36 @@ TEST(RHistStats, DisableDimension) stats.Fill(4, 5, 6, RWeight(1)); EXPECT_EQ(stats.GetNEntries(), 4); + EXPECT_THROW(stats.ComputeMean(1), std::invalid_argument); + EXPECT_THROW(stats.ComputeVariance(1), std::invalid_argument); + EXPECT_THROW(stats.ComputeSkewness(1), std::invalid_argument); + EXPECT_THROW(stats.ComputeKurtosis(1), std::invalid_argument); +} + +TEST(RHistStats, Taint) +{ + RHistStats stats(1); + stats.Taint(); + EXPECT_TRUE(stats.IsTainted()); + + // Modifications are still possible. + stats.Add(stats); + stats.Fill(1); + stats.Scale(2.0); + + // Any read access will throw. + EXPECT_THROW(stats.GetNEntries(), std::logic_error); + EXPECT_THROW(stats.GetSumW(), std::logic_error); + EXPECT_THROW(stats.GetSumW2(), std::logic_error); + EXPECT_THROW(stats.GetDimensionStats(), std::logic_error); + EXPECT_THROW(stats.ComputeMean(), std::logic_error); + EXPECT_THROW(stats.ComputeVariance(), std::logic_error); + EXPECT_THROW(stats.ComputeSkewness(), std::logic_error); + EXPECT_THROW(stats.ComputeKurtosis(), std::logic_error); + + // Clear resets the object, including its taint status. + stats.Clear(); + EXPECT_NO_THROW(stats.GetNEntries()); } TEST(RHistStats, Add) @@ -224,6 +254,27 @@ TEST(RHistStats, AddAtomicDifferent) EXPECT_THROW(statsC.AddAtomic(statsB), std::invalid_argument); } +TEST(RHistStats, AddExceptionSafety) +{ + RHistStats statsA(2); + RHistStats statsB(2); + statsB.DisableDimension(1); + + statsA.Fill(1, 2); + ASSERT_EQ(statsA.GetNEntries(), 1); + statsB.Fill(1, 2); + + EXPECT_THROW(statsA.Add(statsB), std::invalid_argument); + EXPECT_THROW(statsA.AddAtomic(statsB), std::invalid_argument); + + // Verify exception safety. Only the original entry should be there. + EXPECT_EQ(statsA.GetNEntries(), 1); + EXPECT_EQ(statsA.GetSumW(), 1); + EXPECT_EQ(statsA.GetSumW2(), 1); + EXPECT_EQ(statsA.GetDimensionStats(0).fSumWX, 1); + EXPECT_EQ(statsA.GetDimensionStats(1).fSumWX, 2); +} + TEST(RHistStats, Clear) { RHistStats stats(2); @@ -573,6 +624,46 @@ TEST(RHistStats, FillTupleWeightInvalidNumberOfArguments) EXPECT_THROW(stats2.Fill(std::make_tuple(1, 2, 3), RWeight(1)), std::invalid_argument); } +TEST(RHistStats, FillWeightNegative) +{ + RHistStats stats(1); + stats.Fill(1, RWeight(1)); + stats.Fill(1, RWeight(-1)); + + EXPECT_EQ(stats.GetNEntries(), 2); + EXPECT_EQ(stats.GetSumW(), 0); + EXPECT_EQ(stats.GetSumW2(), 2); + // The two weighted entries cancel out each other. + EXPECT_EQ(stats.ComputeNEffectiveEntries(), 0); + + // Cannot compute the mean, and all other computations depend on it. + EXPECT_TRUE(std::isnan(stats.ComputeMean())); + EXPECT_TRUE(std::isnan(stats.ComputeVariance())); + EXPECT_TRUE(std::isnan(stats.ComputeStdDev())); + EXPECT_TRUE(std::isnan(stats.ComputeSkewness())); + EXPECT_TRUE(std::isnan(stats.ComputeKurtosis())); +} + +TEST(RHistStats, FillExceptionSafety) +{ + RHistStats stats(2); + + stats.Fill(1, 2); + ASSERT_EQ(stats.GetNEntries(), 1); + + EXPECT_THROW(stats.Fill(1, "b"), std::invalid_argument); + EXPECT_THROW(stats.Fill(std::make_tuple(1, "b")), std::invalid_argument); + EXPECT_THROW(stats.Fill(1, "b", RWeight(1)), std::invalid_argument); + EXPECT_THROW(stats.Fill(std::make_tuple(1, "b"), RWeight(1)), std::invalid_argument); + + // Verify exception safety. Only the first entry should be there. + EXPECT_EQ(stats.GetNEntries(), 1); + EXPECT_EQ(stats.GetSumW(), 1); + EXPECT_EQ(stats.GetSumW2(), 1); + EXPECT_EQ(stats.GetDimensionStats(0).fSumWX, 1); + EXPECT_EQ(stats.GetDimensionStats(1).fSumWX, 2); +} + TEST(RHistStats, Scale) { RHistStats stats(3); diff --git a/hist/histv7/test/hist_user.cxx b/hist/histv7/test/hist_user.cxx index c7791fa770da3..b5d348da0cdd9 100644 --- a/hist/histv7/test/hist_user.cxx +++ b/hist/histv7/test/hist_user.cxx @@ -11,6 +11,12 @@ struct UserWeight { struct User { double fValue = 0; + User &operator=(double value) + { + fValue = value; + return *this; + } + User &operator++() { fValue++; @@ -252,3 +258,19 @@ TEST(RHistEngineUser, Scale) EXPECT_EQ(engine.GetBinContent(8).fValue, Factor * 0.8); EXPECT_EQ(engine.GetBinContent(9).fValue, Factor * 0.9); } + +TEST(RHistEngineUser, SetBinContent) +{ + // Setting uses operator= + static constexpr std::size_t Bins = 20; + const RRegularAxis axis(Bins, {0, Bins}); + RHistEngine engine({axis}); + + const RBinIndex index(7); + engine.SetBinContent(index, 42); + EXPECT_EQ(engine.GetBinContent(index).fValue, 42); + + const std::array indices = {index}; + engine.SetBinContent(indices, 43); + EXPECT_EQ(engine.GetBinContent(indices).fValue, 43); +} diff --git a/hist/histv7/test/hist_variable.cxx b/hist/histv7/test/hist_variable.cxx index 284958d703100..ed277e38586ea 100644 --- a/hist/histv7/test/hist_variable.cxx +++ b/hist/histv7/test/hist_variable.cxx @@ -332,3 +332,69 @@ TEST(RVariableBinAxis, GetFullRange) EXPECT_EQ(std::distance(full.begin(), full.end()), Bins); } } + +static void Test_RVariableBinAxis_Slice(bool enableFlowBins) +{ + static constexpr std::size_t Bins = 20; + std::vector bins; + for (std::size_t i = 0; i < Bins; i++) { + bins.push_back(i); + } + bins.push_back(Bins); + const RVariableBinAxis origAxis(bins, enableFlowBins); + ASSERT_EQ(origAxis.HasFlowBins(), enableFlowBins); + + // Three different ways of "slicing" which will keep the entire axis. + for (auto sliceSpec : {RSliceSpec{}, RSliceSpec(origAxis.GetFullRange()), RSliceSpec(origAxis.GetNormalRange())}) { + const auto axis = origAxis.Slice(sliceSpec); + EXPECT_EQ(axis.GetNNormalBins(), Bins); + EXPECT_EQ(axis.GetBinEdges(), bins); + EXPECT_TRUE(axis.HasFlowBins()); + } + + { + const RSliceSpec slice(origAxis.GetNormalRange(1, Bins - 1)); + const auto axis = origAxis.Slice(slice); + EXPECT_EQ(axis.GetNNormalBins(), Bins - 2); + EXPECT_EQ(axis.GetBinEdges().front(), 1); + EXPECT_EQ(axis.GetBinEdges().back(), Bins - 1); + EXPECT_TRUE(axis.HasFlowBins()); + } + + { + const RSliceSpec rebin(RSliceSpec::ROperationRebin(2)); + const auto axis = origAxis.Slice(rebin); + EXPECT_EQ(axis.GetNNormalBins(), Bins / 2); + EXPECT_EQ(axis.GetBinEdges().front(), 0); + EXPECT_EQ(axis.GetBinEdges().back(), Bins); + EXPECT_TRUE(axis.HasFlowBins()); + } + + // Rebin grouping must divide the number of normal bins. + EXPECT_THROW(origAxis.Slice(RSliceSpec::ROperationRebin(3)), std::runtime_error); + + // Sum operation makes dimension disappear. + EXPECT_THROW(origAxis.Slice(RSliceSpec::ROperationSum{}), std::runtime_error); + + { + const RSliceSpec sliceRebin(origAxis.GetNormalRange(1, 5), RSliceSpec::ROperationRebin(2)); + const auto axis = origAxis.Slice(sliceRebin); + EXPECT_EQ(axis.GetNNormalBins(), 2); + const auto &binEdges = axis.GetBinEdges(); + ASSERT_EQ(binEdges.size(), 3); + EXPECT_EQ(binEdges[0], 1); + EXPECT_EQ(binEdges[1], 3); + EXPECT_EQ(binEdges[2], 5); + EXPECT_TRUE(axis.HasFlowBins()); + } +} + +TEST(RVariableBinAxis, Slice) +{ + Test_RVariableBinAxis_Slice(true); +} + +TEST(RVariableBinAxis, SliceNoFlowBins) +{ + Test_RVariableBinAxis_Slice(false); +} diff --git a/hist/histv7util/inc/ROOT/Hist/ConvertToTH1.hxx b/hist/histv7util/inc/ROOT/Hist/ConvertToTH1.hxx index 197f9e62cd1a7..c52de19ad7c30 100644 --- a/hist/histv7util/inc/ROOT/Hist/ConvertToTH1.hxx +++ b/hist/histv7util/inc/ROOT/Hist/ConvertToTH1.hxx @@ -79,6 +79,9 @@ std::unique_ptr ConvertToTH1S(const RHist &hist); /// Convert a one-dimensional histogram to TH1I. /// +/// If the RHistStats are tainted, for example after setting bin contents, the number of entries and the total sum of +/// weights will be unset. +/// /// Throws an exception if the histogram has more than one dimension. /// /// \param[in] hist the RHist to convert diff --git a/hist/histv7util/src/ConvertToTH1.cxx b/hist/histv7util/src/ConvertToTH1.cxx index 86f7ee2cd6e8f..76bad7d8f06bd 100644 --- a/hist/histv7util/src/ConvertToTH1.cxx +++ b/hist/histv7util/src/ConvertToTH1.cxx @@ -69,6 +69,10 @@ std::unique_ptr ConvertToTH1Impl(const RHistEngine &engine) template void ConvertGlobalStatistics(Hist &h, const RHistStats &stats) { + if (stats.IsTainted()) { + return; + } + h.SetEntries(stats.GetNEntries()); Double_t hStats[4] = { diff --git a/hist/histv7util/test/hist_convert_TH1.cxx b/hist/histv7util/test/hist_convert_TH1.cxx index 1ab428ec1e5a0..fc4d87bf4e4f7 100644 --- a/hist/histv7util/test/hist_convert_TH1.cxx +++ b/hist/histv7util/test/hist_convert_TH1.cxx @@ -100,6 +100,27 @@ TEST(ConvertToTH1I, RHist) EXPECT_EQ(stats[3], 2470); } +TEST(ConvertToTH1I, RHistSetBinContentTainted) +{ + static constexpr std::size_t Bins = 20; + RHist hist(Bins, {0, Bins}); + hist.SetBinContent(RBinIndex(1), 42); + ASSERT_TRUE(hist.GetStats().IsTainted()); + + auto th1i = ConvertToTH1I(hist); + ASSERT_TRUE(th1i); + + EXPECT_EQ(th1i->GetBinContent(2), 42); + + EXPECT_EQ(th1i->GetEntries(), 0); + Double_t stats[4]; + th1i->GetStats(stats); + EXPECT_EQ(stats[0], 0); + EXPECT_EQ(stats[1], 0); + EXPECT_EQ(stats[2], 0); + EXPECT_EQ(stats[3], 0); +} + TEST(ConvertToTH1C, RHistEngine) { static constexpr std::size_t Bins = 20; @@ -149,7 +170,7 @@ TEST(ConvertToTH1L, RHistEngine) // Set one 64-bit long long value larger than what double can exactly represent. static constexpr long long Large = (1LL << 60) - 1; const std::array indices = {1}; - ROOT::Experimental::Internal::SetBinContent(engineLL, indices, Large); + engineLL.SetBinContent(indices, Large); th1l = ConvertToTH1L(engineLL); ASSERT_TRUE(th1l); diff --git a/interpreter/CppInterOp/.readthedocs.yaml b/interpreter/CppInterOp/.readthedocs.yaml index 5dae8b1275b94..a5b6503c20215 100644 --- a/interpreter/CppInterOp/.readthedocs.yaml +++ b/interpreter/CppInterOp/.readthedocs.yaml @@ -9,8 +9,8 @@ build: tools: python: "3.11" apt_packages: - - clang-18 + - clang-20 - cmake - - libclang-18-dev - - llvm-18-dev - - llvm-18-tools + - libclang-20-dev + - llvm-20-dev + - llvm-20-tools diff --git a/interpreter/CppInterOp/CMakeLists.txt b/interpreter/CppInterOp/CMakeLists.txt index 8a6c9eb79692a..2173240069389 100644 --- a/interpreter/CppInterOp/CMakeLists.txt +++ b/interpreter/CppInterOp/CMakeLists.txt @@ -13,7 +13,7 @@ option(CPPINTEROP_USE_CLING "Use Cling as backend" OFF) option(CPPINTEROP_USE_REPL "Use clang-repl as backend" ON) option(CPPINTEROP_ENABLE_TESTING "Enable the CppInterOp testing infrastructure." ON) if(EMSCRIPTEN) - set(CPPINTEROP_EXTRA_WASM_FLAGS "-sSUPPORT_LONGJMP=wasm -fwasm-exceptions" CACHE STRING "Extra flags for wasm") + set(CPPINTEROP_EXTRA_WASM_FLAGS "-fwasm-exceptions" CACHE STRING "Extra flags for wasm") endif() if (CPPINTEROP_USE_CLING AND CPPINTEROP_USE_REPL) @@ -24,6 +24,13 @@ endif() if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) project(CppInterOp) + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(WARNING "No build type selected. Defaulted CMAKE_BUILD_TYPE=Release.\n" + "Valid options are: None, Debug, Release, RelWithDebInfo, MinSizeRel.") + set(CMAKE_BUILD_TYPE Release CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel" FORCE) + endif() + # LLVM/Clang/Cling default paths if (DEFINED LLVM_DIR) if (NOT DEFINED Clang_DIR) @@ -70,13 +77,13 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) include(GNUInstallDirs) ## Define supported version of clang and llvm - set(CLANG_MIN_SUPPORTED 18.0) + set(CLANG_MIN_SUPPORTED 19.0) set(CLANG_MAX_SUPPORTED "21.1.x") set(CLANG_VERSION_UPPER_BOUND 22.0.0) - set(LLD_MIN_SUPPORTED 18.0) + set(LLD_MIN_SUPPORTED 19.0) set(LLD_MAX_SUPPORTED "21.1.x") set(LLD_VERSION_UPPER_BOUND 22.0.0) - set(LLVM_MIN_SUPPORTED 18.0) + set(LLVM_MIN_SUPPORTED 19.0) set(LLVM_MAX_SUPPORTED "21.1.x") set(LLVM_VERSION_UPPER_BOUND 22.0.0) @@ -373,6 +380,8 @@ endif () # Fixes "C++ exception handler used, but unwind semantics are not enabled" warning Windows if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") + # Required for clang::driver::options::OPT_ see https://github.com/llvm/llvm-project/issues/86028 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Zc:preprocessor") endif () if (APPLE) diff --git a/interpreter/CppInterOp/Emscripten-build-instructions.md b/interpreter/CppInterOp/Emscripten-build-instructions.md index 87b235eefdd4a..cce73735f8c40 100644 --- a/interpreter/CppInterOp/Emscripten-build-instructions.md +++ b/interpreter/CppInterOp/Emscripten-build-instructions.md @@ -316,8 +316,6 @@ Expand-Archive -Path "$PWD\chrome-win.zip" -DestinationPath "$PWD" -Force -Verbo Invoke-WebRequest -Uri "https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=en-US" -OutFile "firefox-setup.exe" -Verbose & "C:\Program Files\7-Zip\7z.exe" x "firefox-setup.exe" $env:PATH="$PWD\core;$PWD\chrome-win;$env:PATH" -echo "PATH=$env:PATH" -echo "PATH=$env:PATH" >> $env:GITHUB_ENV echo "Running CppInterOpTests in Firefox" emrun.bat --browser="firefox.exe" --kill_exit --timeout 60 --browser-args="--headless" CppInterOpTests.html echo "Running DynamicLibraryManagerTests in Firefox" @@ -357,7 +355,7 @@ emcmake cmake \ -DXEUS_CPP_RESOURCE_DIR="$LLVM_BUILD_DIR/lib/clang/$LLVM_VERSION" \ -DSYSROOT_PATH=$SYSROOT_PATH \ .. -EMCC_CFLAGS="-sSUPPORT_LONGJMP=wasm -fwasm-exceptions" emmake make -j $(nproc --all) install +emmake make -j $(nproc --all) install ``` and on Windows by executing @@ -378,9 +376,7 @@ emcmake cmake ` -DXEUS_CPP_RESOURCE_DIR="$env:LLVM_BUILD_DIR/lib/clang/$env:LLVM_VERSION" ` -DSYSROOT_PATH="$env:SYSROOT_PATH" ` .. -$env:EMCC_CFLAGS="-sSUPPORT_LONGJMP=wasm -fwasm-exceptions" emmake make -j $(nproc --all) install -$env:EMCC_CFLAGS="" ``` To build and test Jupyter Lite with this kernel locally on Linux/MacOS you can execute the following diff --git a/interpreter/CppInterOp/README.md b/interpreter/CppInterOp/README.md index 8e93d600ff9dd..a1b4977e6c077 100644 --- a/interpreter/CppInterOp/README.md +++ b/interpreter/CppInterOp/README.md @@ -259,12 +259,8 @@ hosted under the `root-project` (see the git path below). Use the following build instructions to build ```bash -git clone https://github.com/root-project/cling.git -cd ./cling/ -git checkout tags/v1.2 -git apply -v ../CppInterOp/patches/llvm/cling1.2-LookupHelper.patch -cd .. -git clone --depth=1 -b cling-llvm18 https://github.com/root-project/llvm-project.git +git clone --depth=1 --branch v1.3 https://github.com/root-project/cling.git +git clone --depth=1 -b cling-llvm20-20260119-01 https://github.com/root-project/llvm-project.git mkdir llvm-project/build cd llvm-project/build cmake -DLLVM_ENABLE_PROJECTS=clang \ @@ -548,12 +544,8 @@ hosted under the `root-project` (see the git path below). Use the following build instructions to build ```powershell -git clone https://github.com/root-project/cling.git -cd .\cling\ -git checkout tags/v1.2 -git apply -v ..\CppInterOp\patches\llvm\cling1.2-LookupHelper.patch -cd .. -git clone --depth=1 -b cling-llvm18 https://github.com/root-project/llvm-project.git +git clone --depth=1 --branch v1.3 https://github.com/root-project/cling.git +git clone --depth=1 -b cling-llvm20-20260119-01 https://github.com/root-project/llvm-project.git $env:ncpus = $([Environment]::ProcessorCount) $env:PWD_DIR= $PWD.Path $env:CLING_DIR="$env:PWD_DIR\cling" diff --git a/interpreter/CppInterOp/VERSION b/interpreter/CppInterOp/VERSION index 4d12e404b1810..65c4ec8664f24 100644 --- a/interpreter/CppInterOp/VERSION +++ b/interpreter/CppInterOp/VERSION @@ -1 +1 @@ -1.9.0;dev +2.0.0;dev diff --git a/interpreter/CppInterOp/cppinterop-version.tag b/interpreter/CppInterOp/cppinterop-version.tag index 7cfb21d499e7e..522df1a6f38f5 100644 --- a/interpreter/CppInterOp/cppinterop-version.tag +++ b/interpreter/CppInterOp/cppinterop-version.tag @@ -1 +1 @@ -76d06008a66cf8d2a283f2ee1daecc4b81ca7d87 \ No newline at end of file +039bf0423284b1139674525d097e656cb0feb783 \ No newline at end of file diff --git a/interpreter/CppInterOp/docs/DevelopersDocumentation.rst b/interpreter/CppInterOp/docs/DevelopersDocumentation.rst index 77e89238ad3c8..3ce65662f2bb0 100644 --- a/interpreter/CppInterOp/docs/DevelopersDocumentation.rst +++ b/interpreter/CppInterOp/docs/DevelopersDocumentation.rst @@ -147,12 +147,8 @@ build instructions to build on Linux and MacOS .. code:: bash - git clone https://github.com/root-project/cling.git - cd ./cling/ - git checkout tags/v1.2 - git apply -v ../CppInterOp/patches/llvm/cling1.2-LookupHelper.patch - cd .. - git clone --depth=1 -b cling-llvm18 https://github.com/root-project/llvm-project.git + git clone --depth=1 --branch v1.3 https://github.com/root-project/cling.git + git clone --depth=1 -b cling-llvm20-20260119-01 https://github.com/root-project/llvm-project.git mkdir llvm-project/build cd llvm-project/build cmake -DLLVM_ENABLE_PROJECTS=clang \ @@ -173,12 +169,8 @@ Use the following build instructions to build on Windows .. code:: powershell - git clone https://github.com/root-project/cling.git - cd .\cling\ - git checkout tags/v1.2 - git apply -v ..\CppInterOp\patches\llvm\cling1.2-LookupHelper.patch - cd .. - git clone --depth=1 -b cling-llvm18 https://github.com/root-project/llvm-project.git + git clone --depth=1 --branch v1.3 https://github.com/root-project/cling.git + git clone --depth=1 -b cling-llvm20-20260119-01 https://github.com/root-project/llvm-project.git $env:ncpus = $([Environment]::ProcessorCount) $env:PWD_DIR= $PWD.Path $env:CLING_DIR="$env:PWD_DIR\cling" diff --git a/interpreter/CppInterOp/docs/Emscripten-build-instructions.rst b/interpreter/CppInterOp/docs/Emscripten-build-instructions.rst index f7fbd054f5349..5ba93186078e5 100644 --- a/interpreter/CppInterOp/docs/Emscripten-build-instructions.rst +++ b/interpreter/CppInterOp/docs/Emscripten-build-instructions.rst @@ -379,7 +379,7 @@ by executing (replace LLVM_VERSION with the version of llvm you are building aga -DXEUS_CPP_RESOURCE_DIR="$LLVM_BUILD_DIR/lib/clang/$LLVM_VERSION" \ -DSYSROOT_PATH=$SYSROOT_PATH \ .. - EMCC_CFLAGS="-sSUPPORT_LONGJMP=wasm -fwasm-exceptions" emmake make -j $(nproc --all) install + emmake make -j $(nproc --all) install and on Windows by executing @@ -400,9 +400,7 @@ and on Windows by executing -DXEUS_CPP_RESOURCE_DIR="$env:LLVM_BUILD_DIR/lib/clang/$env:LLVM_VERSION" ` -DSYSROOT_PATH="$env:SYSROOT_PATH" ` .. - $env:EMCC_CFLAGS="-sSUPPORT_LONGJMP=wasm -fwasm-exceptions" emmake make -j $(nproc --all) install - $env:EMCC_CFLAGS="" To build and test Jupyter Lite with this kernel locally on Linux/MacOS you can execute the following diff --git a/interpreter/CppInterOp/docs/InstallationAndUsage.rst b/interpreter/CppInterOp/docs/InstallationAndUsage.rst index 911281c25fcf1..a94bbda025b82 100644 --- a/interpreter/CppInterOp/docs/InstallationAndUsage.rst +++ b/interpreter/CppInterOp/docs/InstallationAndUsage.rst @@ -147,12 +147,8 @@ build instructions to build on Linux and MacOS .. code:: bash - git clone https://github.com/root-project/cling.git - cd ./cling/ - git checkout tags/v1.2 - git apply -v ../CppInterOp/patches/llvm/cling1.2-LookupHelper.patch - cd .. - git clone --depth=1 -b cling-llvm18 https://github.com/root-project/llvm-project.git + git clone --depth=1 --branch v1.3 https://github.com/root-project/cling.git + git clone --depth=1 -b cling-llvm20-20260119-01 https://github.com/root-project/llvm-project.git mkdir llvm-project/build cd llvm-project/build cmake -DLLVM_ENABLE_PROJECTS=clang \ @@ -173,12 +169,8 @@ Use the following build instructions to build on Windows .. code:: powershell - git clone https://github.com/root-project/cling.git - cd .\cling\ - git checkout tags/v1.2 - git apply -v ..\CppInterOp\patches\llvm\cling1.2-LookupHelper.patch - cd .. - git clone --depth=1 -b cling-llvm18 https://github.com/root-project/llvm-project.git + git clone --depth=1 --branch v1.3 https://github.com/root-project/cling.git + git clone --depth=1 -b cling-llvm20-20260119-01 https://github.com/root-project/llvm-project.git $env:ncpus = $([Environment]::ProcessorCount) $env:PWD_DIR= $PWD.Path $env:CLING_DIR="$env:PWD_DIR\cling" diff --git a/interpreter/CppInterOp/docs/ReleaseNotes.md b/interpreter/CppInterOp/docs/ReleaseNotes.md index 334ee3057a1bb..83d31884d3ec6 100644 --- a/interpreter/CppInterOp/docs/ReleaseNotes.md +++ b/interpreter/CppInterOp/docs/ReleaseNotes.md @@ -1,7 +1,7 @@ # Introduction This document contains the release notes for the language interoperability -library CppInterOp, release 1.9.0. CppInterOp is built on top of +library CppInterOp, release 2.0.0. CppInterOp is built on top of [Clang](http://clang.llvm.org) and [LLVM](http://llvm.org%3E) compiler infrastructure. Here we describe the status of CppInterOp in some detail, including major improvements from the previous release and new feature work. @@ -16,7 +16,7 @@ interoperability on the fly. In such scenarios CppInterOp can be used to provide the necessary introspection information to the other side helping the language cross talk. -## What's New in CppInterOp 1.9.0? +## What's New in CppInterOp 2.0.0? Some of the major new features and improvements to CppInterOp are listed here. Generic improvements to CppInterOp as a whole or to its underlying @@ -24,8 +24,7 @@ infrastructure are described first. ## External Dependencies -- CppInterOp now works with: - - llvm21 +- CppInterOp v2.0.0 supports llvm 19-21 ## Introspection @@ -48,7 +47,7 @@ infrastructure are described first. [XXX](https://github.com/compiler-research/CppInterOp/issues/XXX) ## Special Kudos @@ -61,6 +60,6 @@ FirstName LastName (#commits) A B (N) diff --git a/interpreter/CppInterOp/docs/conf.py b/interpreter/CppInterOp/docs/conf.py index a0082a3af721b..d8f9dad816acf 100644 --- a/interpreter/CppInterOp/docs/conf.py +++ b/interpreter/CppInterOp/docs/conf.py @@ -50,8 +50,8 @@ html_extra_path = [CPPINTEROP_ROOT + '/build/docs/'] import subprocess -command = 'mkdir {0}/build; cd {0}/build; cmake ../ -DClang_DIR=/usr/lib/llvm-16/build/lib/cmake/clang\ - -DLLVM_DIR=/usr/lib/llvm-16/build/lib/cmake/llvm -DCPPINTEROP_ENABLE_DOXYGEN=ON\ +command = 'mkdir {0}/build; cd {0}/build; cmake ../ -DClang_DIR=/usr/lib/llvm-20/build/lib/cmake/clang\ + -DLLVM_DIR=/usr/lib/llvm-20/build/lib/cmake/llvm -DCPPINTEROP_ENABLE_DOXYGEN=ON\ -DCPPINTEROP_INCLUDE_DOCS=ON'.format(CPPINTEROP_ROOT) subprocess.call(command, shell=True) subprocess.call('doxygen {0}/build/docs/doxygen.cfg'.format(CPPINTEROP_ROOT), shell=True) diff --git a/interpreter/CppInterOp/include/CppInterOp/CppInterOp.h b/interpreter/CppInterOp/include/CppInterOp/CppInterOp.h index b0f7466b05838..0fdcc609a1172 100644 --- a/interpreter/CppInterOp/include/CppInterOp/CppInterOp.h +++ b/interpreter/CppInterOp/include/CppInterOp/CppInterOp.h @@ -102,6 +102,69 @@ enum QualKind : unsigned char { Restrict = 1 << 2 }; +/// Enum modelling programming languages. +enum class InterpreterLanguage : unsigned char { + Unknown, + Asm, + CIR, + LLVM_IR, + C, + CPlusPlus, + ObjC, + ObjCPlusPlus, + OpenCL, + OpenCLCXX, + CUDA, + HIP, + HLSL +}; + +/// Enum modelling language standards. +enum class InterpreterLanguageStandard : unsigned char { + c89, + c94, + gnu89, + c99, + gnu99, + c11, + gnu11, + c17, + gnu17, + c23, + gnu23, + c2y, + gnu2y, + cxx98, + gnucxx98, + cxx11, + gnucxx11, + cxx14, + gnucxx14, + cxx17, + gnucxx17, + cxx20, + gnucxx20, + cxx23, + gnucxx23, + cxx26, + gnucxx26, + opencl10, + opencl11, + opencl12, + opencl20, + opencl30, + openclcpp10, + openclcpp2021, + hlsl, + hlsl2015, + hlsl2016, + hlsl2017, + hlsl2018, + hlsl2021, + hlsl202x, + hlsl202y, + lang_unspecified +}; inline QualKind operator|(QualKind a, QualKind b) { return static_cast(static_cast(a) | static_cast(b)); @@ -728,6 +791,13 @@ CPPINTEROP_API bool ActivateInterpreter(TInterp_t I); ///\returns the current interpreter instance, if any. CPPINTEROP_API TInterp_t GetInterpreter(); +/// Returns the programming language of the interpreter. +CPPINTEROP_API InterpreterLanguage GetLanguage(TInterp_t I = nullptr); + +/// Returns the language standard of the interpreter. +CPPINTEROP_API InterpreterLanguageStandard +GetLanguageStandard(TInterp_t I = nullptr); + /// Sets the Interpreter instance with an external interpreter, meant to /// be called by an external library that manages it's own interpreter. /// Sets a flag signifying CppInterOp does not have ownership of the diff --git a/interpreter/CppInterOp/include/CppInterOp/Dispatch.h b/interpreter/CppInterOp/include/CppInterOp/Dispatch.h index d9f0e9dd291f7..903fd7b84eaff 100644 --- a/interpreter/CppInterOp/include/CppInterOp/Dispatch.h +++ b/interpreter/CppInterOp/include/CppInterOp/Dispatch.h @@ -21,12 +21,6 @@ #error "To use the Dispatch mechanism, do not include CppInterOp.h directly." #endif -#include - -#include -#include -#include - #ifdef _WIN32 #include #undef LoadLibrary @@ -34,6 +28,13 @@ #include #endif +#include + +#include +#include +#include +#include + using CppFnPtrTy = void (*)(); ///\param[in] procname - the name of the FunctionEntry in the symbol lookup /// table. @@ -62,6 +63,8 @@ extern "C" CPPINTEROP_API CppFnPtrTy CppGetProcAddress(const char* procname); DISPATCH_API(IsEnumType, decltype(&CppImpl::IsEnumType)) \ DISPATCH_API(GetIntegerTypeFromEnumType, \ decltype(&CppImpl::GetIntegerTypeFromEnumType)) \ + DISPATCH_API(GetLanguage, decltype(&CppImpl::GetLanguage)) \ + DISPATCH_API(GetLanguageStandard, decltype(&CppImpl::GetLanguageStandard)) \ DISPATCH_API(GetReferencedType, decltype(&CppImpl::GetReferencedType)) \ DISPATCH_API(IsPointerType, decltype(&CppImpl::IsPointerType)) \ DISPATCH_API(GetPointeeType, decltype(&CppImpl::GetPointeeType)) \ @@ -191,14 +194,18 @@ extern "C" CPPINTEROP_API CppFnPtrTy CppGetProcAddress(const char* procname); // TODO: implement overload that takes an existing opened DL handle inline void* dlGetProcAddress(const char* name, const char* customLibPath = nullptr) { - if (!name) - return nullptr; + static auto init = std::make_unique(); + static void* (*getProc)(const char*); - static std::once_flag init; - static void* (*getProc)(const char*) = nullptr; + // magic reset to keep static init inlined in function + if (!name) { + init = std::make_unique(); + getProc = nullptr; + return nullptr; + } // this is currently not tested in a multiple thread/process setup - std::call_once(init, [customLibPath]() { + std::call_once(*init, [customLibPath]() { const char* path = customLibPath ? customLibPath : std::getenv("CPPINTEROP_LIBRARY_PATH"); if (!path) @@ -211,6 +218,9 @@ inline void* dlGetProcAddress(const char* name, GetProcAddress(h, "CppGetProcAddress")); if (!getProc) FreeLibrary(h); + } else { + std::cerr << "[CppInterOp Dispatch] error code=" << GetLastError() + << "\n"; } #else void* handle = dlopen(path, RTLD_LOCAL | RTLD_NOW); @@ -218,12 +228,21 @@ inline void* dlGetProcAddress(const char* name, // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) getProc = reinterpret_cast( dlsym(handle, "CppGetProcAddress")); - if (!getProc) dlclose(handle); + if (!getProc) + dlclose(handle); + } else { + std::cerr << "[CppInterOp Dispatch] " << dlerror() << "\n"; } #endif }); - return getProc ? getProc(name) : nullptr; + if (!getProc) { + init = std::make_unique(); + getProc = nullptr; + return nullptr; + } + + return getProc(name); } // CppAPIType is used for the extern clauses below @@ -253,8 +272,10 @@ CPPINTEROP_API_TABLE /// \param[in] customLibPath Optional custom path to libclangCppInterOp /// \returns true if initialization succeeded, false otherwise inline bool LoadDispatchAPI(const char* customLibPath = nullptr) { +#ifndef NDEBUG std::cout << "[CppInterOp Dispatch] Loading CppInterOp API from " << (customLibPath ? customLibPath : "default library path") << '\n'; +#endif // NDEBUG if (customLibPath) { void* test = dlGetProcAddress("GetInterpreter", customLibPath); if (!test) { @@ -286,6 +307,7 @@ inline void UnloadDispatchAPI() { #define DISPATCH_API(name, type) name = nullptr; CPPINTEROP_API_TABLE #undef DISPATCH_API + dlGetProcAddress(nullptr, nullptr); // this is a magic reset } } // namespace CppInternal::Dispatch diff --git a/interpreter/CppInterOp/include/clang-c/CXCppInterOp.h b/interpreter/CppInterOp/include/clang-c/CXCppInterOp.h index 6570c03389883..d6eefbf721970 100644 --- a/interpreter/CppInterOp/include/clang-c/CXCppInterOp.h +++ b/interpreter/CppInterOp/include/clang-c/CXCppInterOp.h @@ -87,6 +87,74 @@ typedef enum { CXInterpreter_MoreInputExpected = 2, } CXInterpreter_CompilationResult; +/** + * Enum to represent the programming language of the interpreter. + */ +typedef enum { + CXInterpreterLanguage_Unknown, + CXInterpreterLanguage_Asm, + CXInterpreterLanguage_CIR, + CXInterpreterLanguage_LLVM_IR, + CXInterpreterLanguage_C, + CXInterpreterLanguage_CPlusPlus, + CXInterpreterLanguage_ObjC, + CXInterpreterLanguage_ObjCPlusPlus, + CXInterpreterLanguage_OpenCL, + CXInterpreterLanguage_OpenCLCXX, + CXInterpreterLanguage_CUDA, + CXInterpreterLanguage_HIP, + CXInterpreterLanguage_HLSL +} CXInterpreterLanguage; + +/** + * Enum to represent the language standard of the interpreter. + */ +typedef enum { + CXInterpreterLanguageStandard_c89, + CXInterpreterLanguageStandard_c94, + CXInterpreterLanguageStandard_gnu89, + CXInterpreterLanguageStandard_c99, + CXInterpreterLanguageStandard_gnu99, + CXInterpreterLanguageStandard_c11, + CXInterpreterLanguageStandard_gnu11, + CXInterpreterLanguageStandard_c17, + CXInterpreterLanguageStandard_gnu17, + CXInterpreterLanguageStandard_c23, + CXInterpreterLanguageStandard_gnu23, + CXInterpreterLanguageStandard_c2y, + CXInterpreterLanguageStandard_gnu2y, + CXInterpreterLanguageStandard_cxx98, + CXInterpreterLanguageStandard_gnucxx98, + CXInterpreterLanguageStandard_cxx11, + CXInterpreterLanguageStandard_gnucxx11, + CXInterpreterLanguageStandard_cxx14, + CXInterpreterLanguageStandard_gnucxx14, + CXInterpreterLanguageStandard_cxx17, + CXInterpreterLanguageStandard_gnucxx17, + CXInterpreterLanguageStandard_cxx20, + CXInterpreterLanguageStandard_gnucxx20, + CXInterpreterLanguageStandard_cxx23, + CXInterpreterLanguageStandard_gnucxx23, + CXInterpreterLanguageStandard_cxx26, + CXInterpreterLanguageStandard_gnucxx26, + CXInterpreterLanguageStandard_opencl10, + CXInterpreterLanguageStandard_opencl11, + CXInterpreterLanguageStandard_opencl12, + CXInterpreterLanguageStandard_opencl20, + CXInterpreterLanguageStandard_opencl30, + CXInterpreterLanguageStandard_openclcpp10, + CXInterpreterLanguageStandard_openclcpp2021, + CXInterpreterLanguageStandard_hlsl, + CXInterpreterLanguageStandard_hlsl2015, + CXInterpreterLanguageStandard_hlsl2016, + CXInterpreterLanguageStandard_hlsl2017, + CXInterpreterLanguageStandard_hlsl2018, + CXInterpreterLanguageStandard_hlsl2021, + CXInterpreterLanguageStandard_hlsl202x, + CXInterpreterLanguageStandard_hlsl202y, + CXInterpreterLanguageStandard_lang_unspecified +} CXInterpreterLanguageStandard; + /** * Add a search path to the interpreter. * @@ -210,6 +278,26 @@ CINDEX_LINKAGE CXInterpreter_CompilationResult clang_Interpreter_loadLibrary( CINDEX_LINKAGE void clang_Interpreter_unloadLibrary(CXInterpreter I, const char* lib_stem); +/** + * Returns the programming language of the interpreter. + * + * \param I The interpreter. + * + * \returns CXInterpreterLanguage value. + */ +CINDEX_LINKAGE CXInterpreterLanguage +clang_Interpreter_getLanguage(CXInterpreter I); + +/** + * Returns the language standard of the interpreter. + * + * \param I The interpreter. + * + * \returns CXInterpreterLanguageStandard value. + */ +CINDEX_LINKAGE CXInterpreterLanguageStandard +clang_Interpreter_getLanguageStandard(CXInterpreter I); + /** * @} */ diff --git a/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt b/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt index 0383055cd2481..4d7a2c4241c39 100644 --- a/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt +++ b/interpreter/CppInterOp/lib/CppInterOp/CMakeLists.txt @@ -125,9 +125,6 @@ if(EMSCRIPTEN) # Replace newlines with spaces string(REPLACE "\n" " " SYMBOLS_LIST "${SYMBOLS_LIST}") - set_target_properties(clangCppInterOp - PROPERTIES NO_SONAME 1 - ) target_compile_options(clangCppInterOp PRIVATE "SHELL: -Oz" PRIVATE "SHELL: -flto" diff --git a/interpreter/CppInterOp/lib/CppInterOp/CXCppInterOp.cpp b/interpreter/CppInterOp/lib/CppInterOp/CXCppInterOp.cpp index a7f7008baf355..643a9413e5c69 100644 --- a/interpreter/CppInterOp/lib/CppInterOp/CXCppInterOp.cpp +++ b/interpreter/CppInterOp/lib/CppInterOp/CXCppInterOp.cpp @@ -346,30 +346,17 @@ enum CXErrorCode clang_Interpreter_process(CXInterpreter I, const char* code) { } CXValue clang_createValue(void) { -#ifdef CPPINTEROP_USE_CLING - auto val = std::make_unique(); -#else - auto val = std::make_unique(); -#endif // CPPINTEROP_USE_CLING - + auto val = std::make_unique(); return val.release(); } void clang_Value_dispose(CXValue V) { -#ifdef CPPINTEROP_USE_CLING - delete static_cast(V); // NOLINT(*-owning-memory) -#else - delete static_cast(V); // NOLINT(*-owning-memory) -#endif // CPPINTEROP_USE_CLING + delete static_cast(V); // NOLINT(*-owning-memory) } enum CXErrorCode clang_Interpreter_evaluate(CXInterpreter I, const char* code, CXValue V) { -#ifdef CPPINTEROP_USE_CLING - auto* val = static_cast(V); -#else - auto* val = static_cast(V); -#endif // CPPINTEROP_USE_CLING + auto* val = static_cast(V); if (getInterpreter(I)->evaluate(code, *val)) return CXError_Failure; @@ -397,6 +384,17 @@ void clang_Interpreter_unloadLibrary(CXInterpreter I, const char* lib_stem) { interp->getDynamicLibraryManager()->unloadLibrary(lib_stem); } +CXInterpreterLanguage clang_Interpreter_getLanguage(CXInterpreter I) { + return static_cast( + Cpp::GetLanguage(getInterpreter(I))); +} + +CXInterpreterLanguageStandard +clang_Interpreter_getLanguageStandard(CXInterpreter I) { + return static_cast( + Cpp::GetLanguageStandard(getInterpreter(I))); +} + CXString clang_Interpreter_searchLibrariesForSymbol(CXInterpreter I, const char* mangled_name, bool search_system) { diff --git a/interpreter/CppInterOp/lib/CppInterOp/Compatibility.h b/interpreter/CppInterOp/lib/CppInterOp/Compatibility.h index e8bd64864d6cd..56319b5d0b0f7 100644 --- a/interpreter/CppInterOp/lib/CppInterOp/Compatibility.h +++ b/interpreter/CppInterOp/lib/CppInterOp/Compatibility.h @@ -7,12 +7,32 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/GlobalDecl.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/DiagnosticOptions.h" +#if CLANG_VERSION_MAJOR < 21 +#include "clang/Basic/Cuda.h" +#else +#include "clang/Basic/OffloadArch.h" +#endif #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/FileSystem.h" + +#include +#include +#include +#include + #ifdef _MSC_VER #define dup _dup #define dup2 _dup2 @@ -48,38 +68,6 @@ static inline char* GetEnv(const char* Var_Name) { clang::LookupResultKind::FoundOverloaded #endif -#if CLANG_VERSION_MAJOR < 19 -#define Template_Deduction_Result Sema::TemplateDeductionResult -#define Template_Deduction_Result_Success \ - Sema::TemplateDeductionResult::TDK_Success -#else -#define Template_Deduction_Result TemplateDeductionResult -#define Template_Deduction_Result_Success TemplateDeductionResult::Success -#endif - -#if CLANG_VERSION_MAJOR < 19 -#define For_Visible_Redeclaration Sema::ForVisibleRedeclaration -#define Clang_For_Visible_Redeclaration clang::Sema::ForVisibleRedeclaration -#else -#define For_Visible_Redeclaration RedeclarationKind::ForVisibleRedeclaration -#define Clang_For_Visible_Redeclaration \ - RedeclarationKind::ForVisibleRedeclaration -#endif - -#if CLANG_VERSION_MAJOR < 19 -#define CXXSpecialMemberKindDefaultConstructor \ - clang::Sema::CXXDefaultConstructor -#define CXXSpecialMemberKindCopyConstructor clang::Sema::CXXCopyConstructor -#define CXXSpecialMemberKindMoveConstructor clang::Sema::CXXMoveConstructor -#else -#define CXXSpecialMemberKindDefaultConstructor \ - CXXSpecialMemberKind::DefaultConstructor -#define CXXSpecialMemberKindCopyConstructor \ - CXXSpecialMemberKind::CopyConstructor -#define CXXSpecialMemberKindMoveConstructor \ - CXXSpecialMemberKind::MoveConstructor -#endif - #define STRINGIFY(s) STRINGIFY_X(s) #define STRINGIFY_X(...) #__VA_ARGS__ @@ -221,11 +209,12 @@ inline void codeComplete(std::vector& Results, #include "clang/Interpreter/Interpreter.h" #include "clang/Interpreter/Value.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Error.h" +#include "llvm/TargetParser/Host.h" #ifdef LLVM_BUILT_WITH_OOP_JIT #include "clang/Basic/Version.h" -#include "llvm/TargetParser/Host.h" #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" @@ -236,29 +225,162 @@ inline void codeComplete(std::vector& Results, namespace compat { +/// Detect the CUDA installation path using clang::Driver +/// \param args user-provided interpreter arguments (may contain --cuda-path). +/// \param[out] CudaPath the detected CUDA installation path. +/// \returns true on success, false if not found. +inline bool detectCudaInstallPath(const std::vector& args, + std::string& CudaPath) { + // minimal driver that runs CudaInstallationDetector internally + std::string TT = llvm::sys::getProcessTriple(); + llvm::IntrusiveRefCntPtr DiagID( + new clang::DiagnosticIDs()); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + auto* DiagsBuffer = new clang::TextDiagnosticBuffer; +#if CLANG_VERSION_MAJOR < 21 + llvm::IntrusiveRefCntPtr DiagOpts( + new clang::DiagnosticOptions()); + clang::DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer); +#else + clang::DiagnosticOptions DiagOpts; + clang::DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer); +#endif + + clang::driver::Driver D("clang", TT, Diags); + D.setCheckInputsExist(false); + + // construct args: clang -x cuda -c <<< inputs >>> [args] + llvm::SmallVector Argv; + Argv.push_back("clang"); + Argv.push_back("-xcuda"); + Argv.push_back("-c"); + Argv.push_back("<<< inputs >>>"); + for (const auto* arg : args) + Argv.push_back(arg); + + // build a compilation object, which runs the driver's CUDA installation + // detection logic and stores the paths + std::unique_ptr C(D.BuildCompilation(Argv)); + if (!C) + return false; + + // --cuda-path was explicitly provided in user args + if (auto* A = + C->getArgs().getLastArg(clang::driver::options::OPT_cuda_path_EQ)) { + std::string Candidate = A->getValue(); + if (llvm::sys::fs::is_directory(Candidate + "/include")) { + CudaPath = Candidate; + return true; + } + } + + // fallback: clang tries to auto-detect the install, CudaInstallationDetector + // stores the path internally but doesn't expose it, so we look for + // "-internal-isystem /include" that the driver adds for CUDA + // headers. + for (const auto& Job : C->getJobs()) { + if (const auto* Cmd = llvm::dyn_cast(&Job)) { + const auto& Args = Cmd->getArguments(); + for (size_t i = 0; i + 1 < Args.size(); ++i) { + if (llvm::StringRef(Args[i]) == "-internal-isystem") { + llvm::StringRef IncDir(Args[i + 1]); + if (IncDir.ends_with("/include") && + llvm::sys::fs::exists(IncDir.str() + "/cuda.h")) { + CudaPath = IncDir.drop_back(strlen("/include")).str(); + return true; + } + } + } + } + } + return false; +} + +/// Detect GPU architecture via the CUDA Driver API, tweaked from clang's +/// nvptx-arch tool (NVPTXArch.cpp) \param[out] Arch Set to "sm_XX" on success, +/// or clang's default fallback. \returns true on success, false on error (no +/// CUDA driver available). +inline bool detectNVPTXArch(std::string& Arch) { + std::string Err; + // FIXME: Use ToolChain::getSystemGPUArchs() from a minimal driver compilation + // instead, and unify this function with detectCudaInstallPath. Ideally we + // should rely on the offload-arch/nvptx-arch tool in clang, but there is no + // public API or library to link against. + auto Lib = llvm::sys::DynamicLibrary::getPermanentLibrary( +#ifdef _WIN32 + "nvcuda.dll", +#else + "libcuda.so.1", +#endif + &Err); + if (!Lib.isValid()) + return false; + + using cuInit_t = int (*)(unsigned); + using cuDeviceGet_t = int (*)(uint32_t*, int); + using cuDeviceGetAttribute_t = int (*)(int*, int, uint32_t); + + // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) + auto cuInit = reinterpret_cast(Lib.getAddressOfSymbol("cuInit")); + auto cuDeviceGet = + reinterpret_cast(Lib.getAddressOfSymbol("cuDeviceGet")); + auto cuDeviceGetAttribute = reinterpret_cast( + Lib.getAddressOfSymbol("cuDeviceGetAttribute")); + // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) + + if (!cuInit || !cuDeviceGet || !cuDeviceGetAttribute) + return false; + + uint32_t dev; + int maj, min; + if (cuInit(0) || cuDeviceGet(&dev, 0) || + cuDeviceGetAttribute(&maj, /*MAJOR*/ 75, dev) || + cuDeviceGetAttribute(&min, /*MINOR*/ 76, dev)) { + Arch = clang::OffloadArchToString(clang::OffloadArch::CudaDefault); + return true; + } + Arch = "sm_" + std::to_string(maj) + std::to_string(min); + return true; +} + inline std::unique_ptr createClangInterpreter(std::vector& args, int stdin_fd = -1, int stdout_fd = -1, int stderr_fd = -1) { - auto has_arg = [](const char* x, llvm::StringRef match = "cuda") { - llvm::StringRef Arg = x; - Arg = Arg.trim().ltrim('-'); - return Arg == match; - }; - auto it = std::find_if(args.begin(), args.end(), has_arg); - std::vector gpu_args = {it, args.end()}; -#ifdef __APPLE__ bool CudaEnabled = false; -#else - bool CudaEnabled = !gpu_args.empty(); + std::string OffloadArch; + std::string CudaPath; + std::vector CompilerArgs; + for (const auto* arg : args) { + llvm::StringRef A(arg); + llvm::StringRef Stripped = A.trim().ltrim('-'); + if (Stripped == "cuda") { + CudaEnabled = true; + } else if (A.starts_with("--offload-arch=")) { + OffloadArch = A.substr(strlen("--offload-arch=")); + } else if (A.starts_with("--cuda-path=")) { + CudaPath = A.substr(strlen("--cuda-path=")); + } else { + CompilerArgs.push_back(arg); + } + } +#ifdef __APPLE__ + CudaEnabled = false; #endif clang::IncrementalCompilerBuilder CB; - CB.SetCompilerArgs({args.begin(), it}); + CB.SetCompilerArgs(CompilerArgs); std::unique_ptr DeviceCI; if (CudaEnabled) { - // FIXME: Parametrize cuda-path and offload-arch. - CB.SetOffloadArch("sm_35"); + if (OffloadArch.empty()) + detectNVPTXArch(OffloadArch); + + if (CudaPath.empty()) + detectCudaInstallPath(CompilerArgs, CudaPath); + + CB.SetOffloadArch(OffloadArch); + if (!CudaPath.empty()) + CB.SetCudaSDK(CudaPath); auto devOrErr = CB.CreateCudaDevice(); if (!devOrErr) { llvm::logAllUnhandledErrors(devOrErr.takeError(), llvm::errs(), @@ -456,16 +578,11 @@ using Interpreter = CppInternal::Interpreter; class SynthesizingCodeRAII { private: - Interpreter* m_Interpreter; + [[maybe_unused]] Interpreter* m_Interpreter; public: SynthesizingCodeRAII(Interpreter* i) : m_Interpreter(i) {} - ~SynthesizingCodeRAII() { - auto GeneratedPTU = m_Interpreter->Parse(""); - if (!GeneratedPTU) - llvm::logAllUnhandledErrors(GeneratedPTU.takeError(), llvm::errs(), - "Failed to generate PTU:"); - } + // ~SynthesizingCodeRAII() {} // TODO: implement }; } // namespace compat @@ -473,6 +590,12 @@ class SynthesizingCodeRAII { namespace compat { +#ifdef CPPINTEROP_USE_CLING +using Value = cling::Value; +#else +using Value = clang::Value; +#endif + // Clang >= 16 (=16 with Value patch) change castAs to convertTo #ifdef CPPINTEROP_USE_CLING template inline T convertTo(cling::Value V) { diff --git a/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp b/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp index 85588f0fa14aa..9c6f00432765a 100755 --- a/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp +++ b/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp @@ -30,6 +30,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/LangStandard.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" @@ -41,10 +42,8 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Ownership.h" -#include "clang/Sema/Sema.h" -#if CLANG_VERSION_MAJOR >= 19 #include "clang/Sema/Redeclaration.h" -#endif +#include "clang/Sema/Sema.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/SmallString.h" @@ -87,7 +86,7 @@ #ifndef _WIN32 #include #endif - +#include // Stream redirect. #ifdef _WIN32 #include @@ -117,25 +116,14 @@ void* __clang_Interpreter_SetValueWithAlloc(void* This, void* OutVal, void* OpaqueType); #endif -#if CLANG_VERSION_MAJOR > 18 extern "C" void __clang_Interpreter_SetValueNoAlloc(void* This, void* OutVal, void* OpaqueType, ...); -#else -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, - unsigned long long); -#endif #endif // CPPINTEROP_USE_CLING namespace CppImpl { using namespace clang; using namespace llvm; -using namespace std; struct InterpreterInfo { compat::Interpreter* Interpreter = nullptr; @@ -177,11 +165,14 @@ struct InterpreterInfo { // std::deque avoids relocations and calling the dtor of InterpreterInfo. static llvm::ManagedStatic> sInterpreters; -static compat::Interpreter& getInterp() { +static compat::Interpreter& getInterp(TInterp_t I = nullptr) { + if (I) + return *static_cast(I); assert(!sInterpreters->empty() && "Interpreter instance must be set before calling this!"); return *sInterpreters->back().Interpreter; } + static clang::Sema& getSema() { return getInterp().getCI()->getSema(); } static clang::ASTContext& getASTContext() { return getSema().getASTContext(); } @@ -321,6 +312,13 @@ static void InstantiateFunctionDefinition(Decl* D) { getSema().InstantiateFunctionDefinition(SourceLocation(), FD, /*Recursive=*/true, /*DefinitionRequired=*/true); + // FIXME: this can go into a RAII object + clang::DiagnosticsEngine& Diags = getSema().getDiagnostics(); + if (!FD->isDefined() && Diags.hasErrorOccurred()) { + // instantiation failed, need to reset DiagnosticsEngine + Diags.Reset(/*soft=*/true); + Diags.getClient()->clear(); + } } } @@ -414,8 +412,16 @@ bool IsBuiltin(TCppType_t type) { QualType Ty = QualType::getFromOpaquePtr(type); if (Ty->isBuiltinType() || Ty->isAnyComplexType()) return true; - // FIXME: Figure out how to avoid the string comparison. - return llvm::StringRef(Ty.getAsString()).contains("complex"); + // Check for std::complex specializations. + if (const auto* RD = Ty->getAsCXXRecordDecl()) { + if (const auto* CTSD = dyn_cast(RD)) { + IdentifierInfo* II = CTSD->getSpecializedTemplate()->getIdentifier(); + if (II && II->isStr("complex") && + CTSD->getDeclContext()->isStdNamespace()) + return true; + } + } + return false; } bool IsTemplate(TCppScope_t handle) { @@ -598,19 +604,24 @@ std::string GetName(TCppType_t klass) { return ""; } -std::string GetCompleteName(TCppType_t klass) { +static std::string GetCompleteNameImpl(TCppType_t klass, bool qualified) { auto& C = getSema().getASTContext(); auto* D = (Decl*)klass; - PrintingPolicy Policy = C.getPrintingPolicy(); - Policy.SuppressUnwrittenScope = true; - Policy.SuppressScope = true; - Policy.AnonymousTagLocations = false; - Policy.SuppressTemplateArgsInCXXConstructors = false; - Policy.SuppressDefaultTemplateArgs = false; - Policy.AlwaysIncludeTypeForTemplateArgument = true; - if (auto* ND = llvm::dyn_cast_or_null(D)) { + PrintingPolicy Policy = C.getPrintingPolicy(); + Policy.SuppressUnwrittenScope = true; + if (qualified) { + Policy.FullyQualifiedName = true; + Policy.SuppressElaboration = true; + } else { + Policy.SuppressScope = true; + Policy.AnonymousTagLocations = false; + Policy.SuppressTemplateArgsInCXXConstructors = false; + Policy.SuppressDefaultTemplateArgs = false; + Policy.AlwaysIncludeTypeForTemplateArgument = true; + } + if (auto* TD = llvm::dyn_cast(ND)) { std::string type_name; QualType QT = C.getTagDeclType(TD); @@ -620,12 +631,12 @@ std::string GetCompleteName(TCppType_t klass) { if (auto* FD = llvm::dyn_cast(ND)) { std::string func_name; llvm::raw_string_ostream name_stream(func_name); - FD->getNameForDiagnostic(name_stream, Policy, false); + FD->getNameForDiagnostic(name_stream, Policy, qualified); name_stream.flush(); return func_name; } - return ND->getNameAsString(); + return qualified ? ND->getQualifiedNameAsString() : ND->getNameAsString(); } if (llvm::isa_and_nonnull(D)) { @@ -635,6 +646,10 @@ std::string GetCompleteName(TCppType_t klass) { return ""; } +std::string GetCompleteName(TCppType_t klass) { + return GetCompleteNameImpl(klass, /*qualified=*/false); +} + std::string GetQualifiedName(TCppType_t klass) { auto* D = (Decl*)klass; if (auto* ND = llvm::dyn_cast_or_null(D)) { @@ -648,32 +663,8 @@ std::string GetQualifiedName(TCppType_t klass) { return ""; } -// FIXME: Figure out how to merge with GetCompleteName. std::string GetQualifiedCompleteName(TCppType_t klass) { - auto& C = getSema().getASTContext(); - auto* D = (Decl*)klass; - - if (auto* ND = llvm::dyn_cast_or_null(D)) { - if (auto* TD = llvm::dyn_cast(ND)) { - std::string type_name; - QualType QT = C.getTagDeclType(TD); - PrintingPolicy PP = C.getPrintingPolicy(); - PP.FullyQualifiedName = true; - PP.SuppressUnwrittenScope = true; - PP.SuppressElaboration = true; - QT.getAsStringInternal(type_name, PP); - - return type_name; - } - - return ND->getQualifiedNameAsString(); - } - - if (llvm::isa_and_nonnull(D)) { - return ""; - } - - return ""; + return GetCompleteNameImpl(klass, /*qualified=*/true); } std::string GetDoxygenComment(TCppScope_t scope, bool strip_comment_markers) { @@ -1052,7 +1043,7 @@ std::vector GetFunctionsUsingName(TCppScope_t scope, auto& S = getSema(); DeclarationName DName = &getASTContext().Idents.get(name); clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName, - For_Visible_Redeclaration); + RedeclarationKind::ForVisibleRedeclaration); CppInternal::utils::Lookup::Named(&S, R, Decl::castToDeclContext(D)); @@ -1241,7 +1232,7 @@ bool GetClassTemplatedMethods(const std::string& name, TCppScope_t parent, llvm::StringRef Name(name); DeclarationName DName = &getASTContext().Idents.get(name); clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName, - For_Visible_Redeclaration); + RedeclarationKind::ForVisibleRedeclaration); auto* DC = clang::Decl::castToDeclContext(D); CppInternal::utils::Lookup::Named(&S, R, DC); @@ -1827,8 +1818,7 @@ TCppType_t GetUnderlyingType(TCppType_t type) { std::string GetTypeAsString(TCppType_t var) { QualType QT = QualType::getFromOpaquePtr(var); - // FIXME: Get the default printing policy from the ASTContext. - PrintingPolicy Policy((LangOptions())); + PrintingPolicy Policy(getASTContext().getPrintingPolicy()); Policy.Bool = true; // Print bool instead of _Bool. Policy.SuppressTagKeyword = true; // Do not print `class std::string`. Policy.SuppressElaboration = true; @@ -1987,12 +1977,14 @@ TCppType_t GetTypeFromScope(TCppScope_t klass) { return 0; auto* D = (Decl*)klass; - ASTContext& C = getASTContext(); - if (ValueDecl* VD = dyn_cast(D)) + if (auto* VD = dyn_cast(D)) return VD->getType().getAsOpaquePtr(); - return C.getTypeDeclType(cast(D)).getAsOpaquePtr(); + if (auto* TD = dyn_cast(D)) + return getASTContext().getTypeDeclType(TD).getAsOpaquePtr(); + + return (TCppType_t) nullptr; } // Internal functions that are not needed outside the library are @@ -2008,7 +2000,7 @@ enum EReferenceType { kNotReference, kLValueReference, kRValueReference }; // FIXME: Use that routine throughout CallFunc's port in places such as // make_narg_call. -static inline void indent(ostringstream& buf, int indent_level) { +inline void indent(std::ostringstream& buf, int indent_level) { static const std::string kIndentString(" "); for (int i = 0; i < indent_level; ++i) buf << kIndentString; @@ -2489,9 +2481,9 @@ void make_narg_call_with_return(compat::Interpreter& I, const FunctionDecl* FD, if (const CXXConstructorDecl* CD = dyn_cast(FD)) { if (N <= 1 && llvm::isa(FD)) { auto SpecMemKind = I.getCI()->getSema().getSpecialMember(CD); - if ((N == 0 && SpecMemKind == CXXSpecialMemberKindDefaultConstructor) || - (N == 1 && (SpecMemKind == CXXSpecialMemberKindCopyConstructor || - SpecMemKind == CXXSpecialMemberKindMoveConstructor))) { + if ((N == 0 && SpecMemKind == CXXSpecialMemberKind::DefaultConstructor) || + (N == 1 && (SpecMemKind == CXXSpecialMemberKind::CopyConstructor || + SpecMemKind == CXXSpecialMemberKind::MoveConstructor))) { // Using declarations cannot inject special members; do not call // them as such. This might happen by using `Base(Base&, int = 12)`, // which is fine to be called as `Derived d(someBase, 42)` but not @@ -3058,9 +3050,9 @@ static std::string PrepareStructorWrapper(const Decl* D, // // Make the wrapper name. // - string wrapper_name; + std::string wrapper_name; { - ostringstream buf; + std::ostringstream buf; buf << wrapper_prefix; // const NamedDecl* ND = dyn_cast(FD); // string mn; @@ -3103,7 +3095,7 @@ static JitCall::DestructorCall make_dtor_wrapper(compat::Interpreter& interp, // //-- - static map gDtorWrapperStore; + static std::map gDtorWrapperStore; auto I = gDtorWrapperStore.find(D); if (I != gDtorWrapperStore.end()) @@ -3113,12 +3105,12 @@ static JitCall::DestructorCall make_dtor_wrapper(compat::Interpreter& interp, // Make the wrapper name. // std::string class_name; - string wrapper_name = PrepareStructorWrapper(D, "__dtor", class_name); + std::string wrapper_name = PrepareStructorWrapper(D, "__dtor", class_name); // // Write the wrapper code. // int indent_level = 0; - ostringstream buf; + std::ostringstream buf; buf << "__attribute__((used)) "; buf << "extern \"C\" void "; buf << wrapper_name; @@ -3199,7 +3191,7 @@ static JitCall::DestructorCall make_dtor_wrapper(compat::Interpreter& interp, --indent_level; buf << "}\n"; // Done. - string wrapper(buf.str()); + std::string wrapper(buf.str()); // fprintf(stderr, "%s\n", wrapper.c_str()); // // Compile the wrapper code. @@ -3207,7 +3199,7 @@ static JitCall::DestructorCall make_dtor_wrapper(compat::Interpreter& interp, void* F = compile_wrapper(interp, wrapper_name, wrapper, /*withAccessControl=*/false); if (F) { - gDtorWrapperStore.insert(make_pair(D, F)); + gDtorWrapperStore.insert(std::make_pair(D, F)); } else { llvm::errs() << "make_dtor_wrapper" << "Failed to compile\n" @@ -3419,7 +3411,8 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, if (!T.isWasm()) AddLibrarySearchPaths(ResourceDir, I); - I->declare(R"( + if (GetLanguage(I) != InterpreterLanguage::C) { + I->declare(R"( namespace __internal_CppInterOp { template struct function; @@ -3429,6 +3422,7 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, }; } // namespace __internal_CppInterOp )"); + } sInterpreters->emplace_back(I, /*Owned=*/true); @@ -3445,7 +3439,7 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, // obtain mangled name auto* D = static_cast( Cpp::GetNamed("__clang_Interpreter_SetValueWithAlloc")); - if (auto* FD = llvm::dyn_cast(D)) { + if (auto* FD = llvm::dyn_cast_or_null(D)) { auto GD = GlobalDecl(FD); std::string mangledName; compat::maybeMangleDeclName(GD, mangledName); @@ -3454,65 +3448,10 @@ TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, reinterpret_cast(&__clang_Interpreter_SetValueWithAlloc)); } #endif -// llvm < 19 has multiple overloads of __clang_Interpreter_SetValueNoAlloc -#if CLANG_VERSION_MAJOR < 19 - // obtain all 6 candidates, and obtain the correct Decl for each overload - // using BestOverloadFunctionMatch. We then map the decl to the correct - // function pointer (force the compiler to find the right declarion by casting - // to the corresponding function pointer signature) and then register it. - const std::vector Methods = Cpp::GetFunctionsUsingName( - Cpp::GetGlobalScope(), "__clang_Interpreter_SetValueNoAlloc"); - std::string mangledName; - ASTContext& Ctxt = I->getSema().getASTContext(); - auto* TAI = Ctxt.VoidPtrTy.getAsOpaquePtr(); - - // possible parameter lists for __clang_Interpreter_SetValueNoAlloc overloads - // in LLVM 18 - const std::vector> a_params = { - {TAI, TAI, TAI}, - {TAI, TAI, TAI, TAI}, - {TAI, TAI, TAI, Ctxt.FloatTy.getAsOpaquePtr()}, - {TAI, TAI, TAI, Ctxt.DoubleTy.getAsOpaquePtr()}, - {TAI, TAI, TAI, Ctxt.LongDoubleTy.getAsOpaquePtr()}, - {TAI, TAI, TAI, Ctxt.UnsignedLongLongTy.getAsOpaquePtr()}}; - - using FP0 = void (*)(void*, void*, void*); - using FP1 = void (*)(void*, void*, void*, void*); - using FP2 = void (*)(void*, void*, void*, float); - using FP3 = void (*)(void*, void*, void*, double); - using FP4 = void (*)(void*, void*, void*, long double); - using FP5 = void (*)(void*, void*, void*, unsigned long long); - - const std::vector func_pointers = { - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc)), - reinterpret_cast( - static_cast(&__clang_Interpreter_SetValueNoAlloc))}; - - // these symbols are not externed, so we need to mangle their names - for (size_t i = 0; i < a_params.size(); ++i) { - auto* decl = static_cast( - Cpp::BestOverloadFunctionMatch(Methods, {}, a_params[i])); - if (auto* fd = llvm::dyn_cast(decl)) { - auto gd = clang::GlobalDecl(fd); - compat::maybeMangleDeclName(gd, mangledName); - DefineAbsoluteSymbol(*I, mangledName.c_str(), - reinterpret_cast(func_pointers[i])); - } - } -#else + DefineAbsoluteSymbol( *I, "__clang_Interpreter_SetValueNoAlloc", reinterpret_cast(&__clang_Interpreter_SetValueNoAlloc)); -#endif #endif return I; } @@ -3555,6 +3494,38 @@ TInterp_t GetInterpreter() { return sInterpreters->back().Interpreter; } +InterpreterLanguage GetLanguage(TInterp_t I /*=nullptr*/) { + compat::Interpreter* interp = &getInterp(I); + const auto& LO = interp->getCI()->getLangOpts(); + + // CUDA and HIP reuse C++ language standards, so LangStd alone reports CXX. + if (LO.CUDA) + return InterpreterLanguage::CUDA; + if (LO.HIP) + return InterpreterLanguage::HIP; + + auto standard = clang::LangStandard::getLangStandardForKind(LO.LangStd); + auto lang = static_cast(standard.getLanguage()); + assert(lang != InterpreterLanguage::Unknown && "Unknown language"); + assert(static_cast(lang) <= + static_cast(InterpreterLanguage::HLSL) && + "Unhandled Language"); + return lang; +} + +InterpreterLanguageStandard GetLanguageStandard(TInterp_t I /*=nullptr*/) { + compat::Interpreter* interp = &getInterp(I); + const auto& LO = interp->getCI()->getLangOpts(); + auto langStandard = static_cast(LO.LangStd); + assert(langStandard != InterpreterLanguageStandard::lang_unspecified && + "Unspecified language standard"); + assert(static_cast(langStandard) <= + static_cast( + InterpreterLanguageStandard::lang_unspecified) && + "Unhandled language standard."); + return langStandard; +} + void UseExternalInterpreter(TInterp_t I) { assert(sInterpreters->empty() && "sInterpreter already in use!"); sInterpreters->emplace_back(static_cast(I), @@ -3668,11 +3639,7 @@ int Declare(const char* code, bool silent) { int Process(const char* code) { return getInterp().process(code); } intptr_t Evaluate(const char* code, bool* HadError /*=nullptr*/) { -#ifdef CPPINTEROP_USE_CLING - cling::Value V; -#else - clang::Value V; -#endif // CPPINTEROP_USE_CLING + compat::Value V; if (HadError) *HadError = false; @@ -3806,10 +3773,10 @@ static Decl* InstantiateTemplate(TemplateDecl* TemplateD, if (auto* FunctionTemplate = dyn_cast(TemplateD)) { FunctionDecl* Specialization = nullptr; clang::sema::TemplateDeductionInfo Info(fakeLoc); - Template_Deduction_Result Result = + TemplateDeductionResult Result = S.DeduceTemplateArguments(FunctionTemplate, &TLI, Specialization, Info, /*IsAddressOfFunction*/ true); - if (Result != Template_Deduction_Result_Success) { + if (Result != TemplateDeductionResult::Success) { // FIXME: Diagnose what happened. (void)Result; } diff --git a/interpreter/CppInterOp/lib/CppInterOp/CppInterOpInterpreter.h b/interpreter/CppInterOp/lib/CppInterOp/CppInterOpInterpreter.h index 83f17df7d3dbf..d4cd3d501124b 100644 --- a/interpreter/CppInterOp/lib/CppInterOp/CppInterOpInterpreter.h +++ b/interpreter/CppInterOp/lib/CppInterOp/CppInterOpInterpreter.h @@ -22,10 +22,8 @@ #include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/Sema.h" -#if CLANG_VERSION_MAJOR >= 19 #include "clang/Sema/Redeclaration.h" -#endif +#include "clang/Sema/Sema.h" #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/DenseMap.h" @@ -123,7 +121,7 @@ inline clang::NamedDecl* Named(clang::Sema* S, const clang::DeclContext* Within = nullptr) { clang::LookupResult R(*S, Name, clang::SourceLocation(), clang::Sema::LookupOrdinaryName, - Clang_For_Visible_Redeclaration); + RedeclarationKind::ForVisibleRedeclaration); Named(S, R, Within); return LookupResult2Decl(R); } diff --git a/interpreter/CppInterOp/unittests/CppInterOp/CMakeLists.txt b/interpreter/CppInterOp/unittests/CppInterOp/CMakeLists.txt index 4f0a4f98e2061..1d6ccd3e86548 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/CMakeLists.txt +++ b/interpreter/CppInterOp/unittests/CppInterOp/CMakeLists.txt @@ -5,6 +5,49 @@ if (EMSCRIPTEN) # For Emscripten builds linking to gtest_main will not suffice for gtest to run # the tests and an explicitly main.cpp is needed set(EXTRA_TEST_SOURCE_FILES main.cpp) + + string(REPLACE "@" "@@" ESCAPED_SYSROOT_PATH "${SYSROOT_PATH}") + # Explanation of Emscripten-specific link flags for CppInterOpTests: + # + # MAIN_MODULE=1: + # Enables building CppInterOpTests.js as the main WebAssembly module, allowing dynamic linking of side modules. + # + # WASM_BIGINT: + # Ensures support for 64-bit integer types by enabling JavaScript BigInt integration in WASM. + # + # ALLOW_MEMORY_GROWTH=1: + # Allows the WebAssembly memory to grow dynamically at runtime to accommodate increasing memory needs. + # Would lead to an abortOnCannotGrowMemory error if memory cannot be grown while running the tests. + # + # STACK_SIZE=32mb: Allocates 32MB of stack space to handle deep recursion or large stack-allocated objects safely. + # INITIAL_MEMORY=128mb: Sets the initial linear memory size to 128MB to reduce the likelihood of early memory expansion and improve performance. + # The STACK_SIZE and INITIAL_MEMORY values are chosen based on what has been put to use for running xeus-cpp-lite. + # Check https://github.com/jupyter-xeus/xeus/blob/main/cmake/WasmBuildOptions.cmake#L35-L36 for more details. + # Not setting these flags would lead to a memory access out of bounds error while running the tests. + # + # --preload-file ${SYSROOT_PATH}/include@/include: + # Preloads the system include directory into the Emscripten virtual filesystem to make headers accessible at runtime. + # + # --emrun + # Makes it so that we run the html file created by this target, that we can capture the standard output + # and output to the terminal + + # Common compile flags for WASM tests + set(CPPINTEROP_COMMON_WASM_TEST_COMPILE_FLAGS + "SHELL:${CPPINTEROP_EXTRA_WASM_FLAGS}" + ) + + # Common link flags for WASM tests + set(CPPINTEROP_COMMON_WASM_TEST_LINK_FLAGS + "SHELL:${CPPINTEROP_EXTRA_WASM_FLAGS}" + "SHELL:-s MAIN_MODULE=1" + "SHELL:-s WASM_BIGINT" + "SHELL:-s ALLOW_MEMORY_GROWTH=1" + "SHELL:-s STACK_SIZE=32mb" + "SHELL:-s INITIAL_MEMORY=64mb" + "SHELL:--preload-file ${ESCAPED_SYSROOT_PATH}/include@/include" + "SHELL:--emrun" + ) else() # Do not need main.cpp for native builds, but we do have GPU support for native builds set(EXTRA_TEST_SOURCE_FILES CUDATest.cpp) @@ -35,43 +78,11 @@ set_source_files_properties(InterpreterTest.cpp PROPERTIES COMPILE_DEFINITIONS ) if(EMSCRIPTEN) - string(REPLACE "@" "@@" ESCAPED_SYSROOT_PATH "${SYSROOT_PATH}") - # Explanation of Emscripten-specific link flags for CppInterOpTests: - # - # MAIN_MODULE=1: - # Enables building CppInterOpTests.js as the main WebAssembly module, allowing dynamic linking of side modules. - # - # WASM_BIGINT: - # Ensures support for 64-bit integer types by enabling JavaScript BigInt integration in WASM. - # - # ALLOW_MEMORY_GROWTH=1: - # Allows the WebAssembly memory to grow dynamically at runtime to accommodate increasing memory needs. - # Would lead to an abortOnCannotGrowMemory error if memory cannot be grown while running the tests. - # - # STACK_SIZE=32mb: Allocates 32MB of stack space to handle deep recursion or large stack-allocated objects safely. - # INITIAL_MEMORY=128mb: Sets the initial linear memory size to 128MB to reduce the likelihood of early memory expansion and improve performance. - # The STACK_SIZE and INITIAL_MEMORY values are chosen based on what has been put to use for running xeus-cpp-lite. - # Check https://github.com/jupyter-xeus/xeus/blob/main/cmake/WasmBuildOptions.cmake#L35-L36 for more details. - # Not setting these flags would lead to a memory access out of bounds error while running the tests. - # - # --preload-file ${SYSROOT_PATH}/include@/include: - # Preloads the system include directory into the Emscripten virtual filesystem to make headers accessible at runtime. - # - # --emrun - # Makes it so that we run the html file created by this target, that we can capture the standard output - # and output to the terminal target_compile_options(CppInterOpTests - PUBLIC "SHELL: ${CPPINTEROP_EXTRA_WASM_FLAGS}" + PUBLIC ${CPPINTEROP_COMMON_WASM_TEST_COMPILE_FLAGS} ) target_link_options(CppInterOpTests - PUBLIC "SHELL: ${CPPINTEROP_EXTRA_WASM_FLAGS}" - PUBLIC "SHELL: -s MAIN_MODULE=1" - PUBLIC "SHELL: -s WASM_BIGINT" - PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1" - PUBLIC "SHELL: -s STACK_SIZE=32mb" - PUBLIC "SHELL: -s INITIAL_MEMORY=128mb" - PUBLIC "SHELL: --preload-file ${ESCAPED_SYSROOT_PATH}/include@/include" - PUBLIC "SHELL: --emrun" + PUBLIC ${CPPINTEROP_COMMON_WASM_TEST_LINK_FLAGS} ) endif() @@ -90,20 +101,13 @@ add_cppinterop_unittest(DynamicLibraryManagerTests if(EMSCRIPTEN) set(TEST_SHARED_LIBRARY_PATH "${CMAKE_CURRENT_BINARY_DIR}/bin/$/") string(REPLACE "@" "@@" ESCAPED_TEST_SHARED_LIBRARY_PATH "${TEST_SHARED_LIBRARY_PATH}") - # Check explanation of Emscripten-specific link flags for CppInterOpTests above for DynamicLibraryManagerTests as well. target_compile_options(DynamicLibraryManagerTests - PUBLIC "SHELL: ${CPPINTEROP_EXTRA_WASM_FLAGS}" + PUBLIC ${CPPINTEROP_COMMON_WASM_TEST_COMPILE_FLAGS} ) target_link_options(DynamicLibraryManagerTests - PUBLIC "SHELL: ${CPPINTEROP_EXTRA_WASM_FLAGS}" - PUBLIC "SHELL: -s MAIN_MODULE=1" - PUBLIC "SHELL: -s WASM_BIGINT" - PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1" - PUBLIC "SHELL: -s STACK_SIZE=32mb" - PUBLIC "SHELL: -s INITIAL_MEMORY=128mb" - PUBLIC "SHELL: --preload-file ${ESCAPED_SYSROOT_PATH}/include@/include" - PUBLIC "SHELL: --emrun" - PUBLIC "SHELL: --preload-file ${ESCAPED_TEST_SHARED_LIBRARY_PATH}/libTestSharedLib.so@/libTestSharedLib.so" + PUBLIC + ${CPPINTEROP_COMMON_WASM_TEST_LINK_FLAGS} + "SHELL:--preload-file ${ESCAPED_TEST_SHARED_LIBRARY_PATH}/libTestSharedLib.so@/libTestSharedLib.so" ) endif() diff --git a/interpreter/CppInterOp/unittests/CppInterOp/CUDATest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/CUDATest.cpp index fe0e904a1b376..5c6fc0fecd555 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/CUDATest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/CUDATest.cpp @@ -2,81 +2,212 @@ #include "CppInterOp/CppInterOp.h" -#include "clang/Basic/Version.h" +#include "llvm/Support/FileSystem.h" #include "gtest/gtest.h" #include +#include +#include using namespace TestUtils; -static bool HasCudaSDK() { - auto supportsCudaSDK = []() { -#ifdef CPPINTEROP_USE_CLING - // FIXME: Enable this for cling. - return false; +// CUDA test fixture that runs SDK and runtime checks once for the entire suite. +class CUDATest : public ::testing::Test { +protected: + static inline bool HasSDK = false; + static inline bool HasRuntime = false; + + static void SetUpTestSuite() { +#if defined(CPPINTEROP_USE_CLING) || defined(_WIN32) + return; // FIXME: Enable for cling and Windows. #endif - if (!Cpp::CreateInterpreter({}, {"--cuda"})) - return false; - return Cpp::Declare("__global__ void test_func() {}" - "test_func<<<1,1>>>();" DFLT_FALSE) == 0; - }; - static bool hasCuda = supportsCudaSDK(); - return hasCuda; + auto *I = Cpp::CreateInterpreter({}, {"--cuda"}); + if (!I) + return; + if (Cpp::Declare("__global__ void test_func() {}" + "test_func<<<1,1>>>();" DFLT_FALSE) != 0) + return; + + HasSDK = true; + + if (Cpp::Declare("cudaDeviceSynchronize();" DFLT_FALSE) != 0) { + Cpp::DeleteInterpreter(I); + return; + } + bool evalErr = false; + int cudaErr = (int)Cpp::Evaluate("(int)cudaGetLastError()", &evalErr); + if (evalErr || cudaErr != 0) + GTEST_LOG_(WARNING) << "CUDA Kernel execution failed (cudaError=" + << cudaErr << "). Runtime tests will be skipped."; + else + HasRuntime = true; + Cpp::DeleteInterpreter(I); + } +}; + +#define SKIP_IF_NO_SDK \ + if (!HasSDK) { \ + GTEST_SKIP() << "CUDA SDK not found"; \ + return; \ + } + +#define SKIP_IF_NO_RUNTIME \ + if (!HasRuntime) { \ + GTEST_SKIP() << "CUDA runtime not available"; \ + return; \ + } + +TEST_F(CUDATest, Sanity) { + SKIP_IF_NO_SDK; + EXPECT_TRUE(Cpp::CreateInterpreter({}, {"--cuda"})); } -static bool HasCudaRuntime() { - auto supportsCuda = []() { -#ifdef CPPINTEROP_USE_CLING - // FIXME: Enable this for cling. - return false; +#ifndef CPPINTEROP_USE_CLING +TEST_F(CUDATest, DetectCudaInstallAndArch) { + SKIP_IF_NO_SDK; + + std::string path; + std::vector args; + + // no args: rely on auto-detect + EXPECT_TRUE(compat::detectCudaInstallPath(args, path)); + EXPECT_TRUE(llvm::StringRef(path).starts_with("/usr/local/cuda")); + + // explicit path (self-hosted CUDA runners are on 12.3) + args = {"--cuda-path=/usr/local/cuda-12.3"}; + if (compat::detectCudaInstallPath(args, path)) { + if (llvm::sys::fs::is_directory("/usr/local/cuda-12.3/include")) + EXPECT_EQ(path, "/usr/local/cuda-12.3"); + else + EXPECT_TRUE(llvm::StringRef(path).starts_with("/usr/local/cuda")); + } + + // user provided path that doesn't exist should fail + args = {"--cuda-path=/nonexistent"}; + EXPECT_FALSE(compat::detectCudaInstallPath(args, path)); + + // GPU offload arch detection + std::string arch; + EXPECT_TRUE(compat::detectNVPTXArch(arch)); + EXPECT_TRUE(llvm::StringRef(arch).starts_with("sm_")); + + EXPECT_TRUE(Cpp::CreateInterpreter( + {}, {"--cuda", "--cuda-path=/usr/local/cuda-12.3", + "--offload-arch=sm_70"})); +} #endif - if (!HasCudaSDK()) - return false; - if (!Cpp::CreateInterpreter({}, {"--cuda"})) - return false; - if (Cpp::Declare("__global__ void test_func() {}" - "test_func<<<1,1>>>();" DFLT_FALSE)) - return false; - intptr_t result = Cpp::Evaluate("(bool)cudaGetLastError()" DFLT_NULLPTR); - return !(bool)result; - }; - static bool hasCuda = supportsCuda(); - return hasCuda; +TEST_F(CUDATest, CUDAH) { + SKIP_IF_NO_SDK; + + Cpp::CreateInterpreter({}, {"--cuda"}); + EXPECT_EQ(0, Cpp::Declare("#include " DFLT_FALSE)); } -#ifdef CPPINTEROP_USE_CLING -TEST(DISABLED_CUDATest, Sanity) { -#else -TEST(CUDATest, Sanity) { -#endif -#ifdef _WIN32 - GTEST_SKIP() << "Disabled on Windows. Needs fixing."; -#endif - if (!HasCudaSDK()) - GTEST_SKIP() << "Skipping CUDA tests as CUDA SDK not found"; - EXPECT_TRUE(Cpp::CreateInterpreter({}, {"--cuda"})); +TEST_F(CUDATest, CUDARuntime) { + SKIP_IF_NO_RUNTIME; + + Cpp::CreateInterpreter({}, {"--cuda"}); + EXPECT_EQ(0, Cpp::Declare(R"( + int deviceCount = 0; + cudaGetDeviceCount(&deviceCount); + )" DFLT_FALSE)); + bool err = false; + intptr_t count = Cpp::Evaluate("deviceCount", &err); + EXPECT_FALSE(err); + EXPECT_GT((int)count, 0); } -TEST(CUDATest, CUDAH) { -#ifdef _WIN32 - GTEST_SKIP() << "Disabled on Windows. Needs fixing."; -#endif - if (!HasCudaSDK()) - GTEST_SKIP() << "Skipping CUDA tests as CUDA SDK not found"; +TEST_F(CUDATest, Interpreter_GetLanguageCUDA) { + SKIP_IF_NO_RUNTIME; Cpp::CreateInterpreter({}, {"--cuda"}); - bool success = !Cpp::Declare("#include " DFLT_FALSE); - EXPECT_TRUE(success); + EXPECT_EQ(Cpp::GetLanguage(nullptr), Cpp::InterpreterLanguage::CUDA); } -TEST(CUDATest, CUDARuntime) { -#ifdef _WIN32 - GTEST_SKIP() << "Disabled on Windows. Needs fixing."; -#endif - if (!HasCudaRuntime()) - GTEST_SKIP() << "Skipping CUDA tests as CUDA runtime not found"; +TEST_F(CUDATest, SimpleKernelExecution) { + SKIP_IF_NO_RUNTIME; + + Cpp::CreateInterpreter({}, {"--cuda"}); + EXPECT_EQ(0, Cpp::Declare(R"( + __global__ void addOne(int* x) { *x += 1; } + int* d; + cudaMallocManaged(&d, sizeof(int)); + *d = 41; + addOne<<<1,1>>>(d); + cudaDeviceSynchronize(); + int kernelErr = (int)cudaGetLastError(); + )" DFLT_FALSE)) + << "Failed to declare/launch kernel"; + + bool err = false; + int cudaErr = (int)Cpp::Evaluate("kernelErr", &err); + EXPECT_FALSE(err); + EXPECT_EQ(cudaErr, 0) << "Simple kernel launch failed"; + + if (cudaErr == 0) { + intptr_t result = Cpp::Evaluate("*d", &err); + EXPECT_FALSE(err); + EXPECT_EQ((int)result, 42); + } + + Cpp::Declare("cudaFree(d);" DFLT_FALSE); +} + +// demonstrate incremental CUDA compilation with CUB BlockReduce +// with a __device__ transform, multi-block atomicAdd +TEST_F(CUDATest, CUB_BlockReduceWithDeviceFunction) { + SKIP_IF_NO_RUNTIME; + + Cpp::CreateInterpreter({}, {"--cuda"}); + + EXPECT_EQ(0, Cpp::Declare(R"( + #include + + constexpr int BLOCK_SIZE = 128; + + __device__ int transform(int x) { return x * x; } + + __global__ void sumOfSquaresKernel(const int* __restrict__ input, + int* __restrict__ output, int N) { + using BlockReduceT = cub::BlockReduce; + __shared__ typename BlockReduceT::TempStorage temp_storage; + + int idx = blockIdx.x * BLOCK_SIZE + threadIdx.x; + int val = (idx < N) ? transform(input[idx]) : 0; + int block_sum = BlockReduceT(temp_storage).Sum(val); + if (threadIdx.x == 0) + atomicAdd(output, block_sum); + } + )" DFLT_FALSE)) + << "Failed to declare kernel"; + + EXPECT_EQ(0, Cpp::Declare(R"( + const int N = 256; + int* d_in; + int* d_out; + cudaMallocManaged(&d_in, N * sizeof(int)); + cudaMallocManaged(&d_out, sizeof(int)); + for (int i = 0; i < N; i++) d_in[i] = i + 1; // 1..256 + *d_out = 0; + int numBlocks = (N + BLOCK_SIZE - 1) / BLOCK_SIZE; + sumOfSquaresKernel<<>>(d_in, d_out, N); + cudaError_t syncErr = cudaDeviceSynchronize(); + cudaError_t lastErr = cudaGetLastError(); + )" DFLT_FALSE)) + << "Failed to launch kernel"; + + bool err = false; + EXPECT_EQ((int)Cpp::Evaluate("(int)syncErr", &err), 0); + EXPECT_FALSE(err); + EXPECT_EQ((int)Cpp::Evaluate("(int)lastErr", &err), 0); + EXPECT_FALSE(err); + + // read result directly from managed memory + intptr_t result = Cpp::Evaluate("*d_out", &err); + EXPECT_FALSE(err); + EXPECT_EQ((int)result, 5625216); - EXPECT_TRUE(HasCudaRuntime()); + Cpp::Declare("cudaFree(d_in); cudaFree(d_out);" DFLT_FALSE); } diff --git a/interpreter/CppInterOp/unittests/CppInterOp/DispatchTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/DispatchTest.cpp index 2468bdfef6dc4..13a313b29f781 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/DispatchTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/DispatchTest.cpp @@ -68,4 +68,19 @@ TEST(CPPINTEROP_TEST_MODE, DispatchAPI_CppGetProcAddress_Advanced) { EXPECT_NE(demangled_add_double.find(GetQualifiedCompleteNameFn(Decls[1])), std::string::npos); } + +TEST(CPPINTEROP_TEST_MODE, DispatchAPI_LoadUnloadCycle) { + Cpp::UnloadDispatchAPI(); // make sure we're no loaded already... + EXPECT_FALSE(Cpp::LoadDispatchAPI("some/random/invalid/directory.so")); + + Cpp::UnloadDispatchAPI(); // should reset for next load to be successfull + EXPECT_TRUE(Cpp::LoadDispatchAPI(CPPINTEROP_LIB_PATH)); + + Cpp::UnloadDispatchAPI(); // should reset for next load to fail + EXPECT_FALSE(Cpp::LoadDispatchAPI("some/other/random/invalid/directory.so")); + + // NOTE: minimize side-effects: reload assuming the static set is still + // and other test may depend of this being loaded + EXPECT_TRUE(Cpp::LoadDispatchAPI(CPPINTEROP_LIB_PATH)); +} // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) diff --git a/interpreter/CppInterOp/unittests/CppInterOp/DynamicLibraryManagerTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/DynamicLibraryManagerTest.cpp index ab3ca812581ef..bee559b426c76 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/DynamicLibraryManagerTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/DynamicLibraryManagerTest.cpp @@ -25,7 +25,7 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, DynamicLibraryManager_Sanity) { GTEST_SKIP() << "Test fails for Emscipten builds"; #endif -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && \ defined(_WIN32) GTEST_SKIP() << "Test fails with Cling on Windows"; #endif diff --git a/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp index 1b717064b0bc0..32ecc062aef35 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -703,10 +703,6 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, FunctionReflection_ExistsFunctionTemplate) { TYPED_TEST(CPPINTEROP_TEST_MODE, FunctionReflection_InstantiateTemplateFunctionFromString) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; -#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; std::vector interpreter_args = { "-include", "new" }; @@ -1631,6 +1627,9 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, FunctionReflection_JitCallAdvanced) { #if CLANG_VERSION_MAJOR < 20 GTEST_SKIP() << "Test fails for Emscipten builds"; #endif +#endif +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && defined(_WIN32) + GTEST_SKIP() << "Test fails with Cling on Windows"; #endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; @@ -2843,6 +2842,10 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, FunctionReflection_UndoTest) { #ifdef _WIN32 GTEST_SKIP() << "Disabled on Windows. Needs fixing."; #endif +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && \ + defined(__APPLE__) + GTEST_SKIP() << "Disabled on osx for cling based on llvm 20. Needs fixing."; +#endif #ifdef EMSCRIPTEN GTEST_SKIP() << "Test fails for Emscipten builds"; #else diff --git a/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp index 2c0e70f37df5d..51652a5c6594b 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/InterpreterTest.cpp @@ -17,8 +17,9 @@ #include "clang-c/CXCppInterOp.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include #include #include "gtest/gtest.h" @@ -31,11 +32,11 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_Version) { EXPECT_THAT(Cpp::GetVersion(), StartsWith("CppInterOp version")); } -#ifdef NDEBUG +#ifndef LLVM_ENABLE_ASSERTIONS TYPED_TEST(CPPINTEROP_TEST_MODE, DISABLED_Interpreter_DebugFlag) { #else TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_DebugFlag) { -#endif // NDEBUG +#endif // LLVM_ENABLE_ASSERTIONS TestFixture::CreateInterpreter(); EXPECT_FALSE(Cpp::IsDebugOutputEnabled()); std::string cerrs; @@ -318,7 +319,10 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_IncludePaths) { } TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_CodeCompletion) { -#if CLANG_VERSION_MAJOR >= 18 || defined(CPPINTEROP_USE_CLING) +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && \ + defined(_WIN32) + GTEST_SKIP() << "Test fails with Cling on Windows"; +#endif TestFixture::CreateInterpreter(); std::vector cc; Cpp::Declare("int foo = 12;" DFLT_FALSE); @@ -332,9 +336,75 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_CodeCompletion) { if (r == "float" || r == "foo") cnt++; EXPECT_EQ(2U, cnt); // float and foo -#else - GTEST_SKIP(); -#endif +} + +TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_GetLanguageCpp) { + // Default interpreter (C++14) + TestFixture::CreateInterpreter(); + EXPECT_EQ(Cpp::GetLanguage(nullptr), Cpp::InterpreterLanguage::CPlusPlus); +} + +TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_GetLanguageStandardCpp) { + // Other C++ standards + TestFixture::CreateInterpreter({"-std=c++14"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::cxx14); + + TestFixture::CreateInterpreter({"-std=c++17"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::cxx17); + + TestFixture::CreateInterpreter({"-std=c++20"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::cxx20); + + TestFixture::CreateInterpreter({"-std=c++23"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::cxx23); +} + +TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_GetLanguageCAPI) { + auto* I = TestFixture::CreateInterpreter(); + auto* CXI = clang_createInterpreterFromRawPtr(I); + EXPECT_EQ(clang_Interpreter_getLanguage(CXI), + CXInterpreterLanguage_CPlusPlus); + EXPECT_EQ(clang_Interpreter_getLanguageStandard(CXI), + CXInterpreterLanguageStandard_cxx14); + clang_Interpreter_dispose(CXI); +} + +TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_GetLanguageC) { + TestFixture::CreateInterpreter({"-xc", "-std=c99"}); + EXPECT_EQ(Cpp::GetLanguage(nullptr), Cpp::InterpreterLanguage::C); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::c99); +} +TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_GetLanguageStandardC) { + TestFixture::CreateInterpreter({"-xc", "-std=c89"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::c89); + + TestFixture::CreateInterpreter({"-xc", "-std=c11"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::c11); + + TestFixture::CreateInterpreter({"-xc", "-std=c17"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::c17); + + TestFixture::CreateInterpreter({"-xc", "-std=c23"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::c23); +} + +TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_GetLanguageStandardGNU) { + TestFixture::CreateInterpreter({"-std=gnu++14"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::gnucxx14); + + TestFixture::CreateInterpreter({"-std=gnu++17"}); + EXPECT_EQ(Cpp::GetLanguageStandard(nullptr), + Cpp::InterpreterLanguageStandard::gnucxx17); } TYPED_TEST(CPPINTEROP_TEST_MODE, Interpreter_ExternalInterpreter) { diff --git a/interpreter/CppInterOp/unittests/CppInterOp/ScopeReflectionTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/ScopeReflectionTest.cpp index 5d828fc59e6ad..3aece27b73000 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/ScopeReflectionTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/ScopeReflectionTest.cpp @@ -209,11 +209,6 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_SizeOf) { } TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IsBuiltin) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; -#endif - // static std::set g_builtins = // {"bool", "char", "signed char", "unsigned char", "wchar_t", "short", "unsigned short", // "int", "unsigned int", "long", "unsigned long", "long long", "unsigned long long", @@ -242,6 +237,13 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IsBuiltin) { auto *CTD = cast(lookup.front()); for (ClassTemplateSpecializationDecl *CTSD : CTD->specializations()) EXPECT_TRUE(Cpp::IsBuiltin(C.getTypeDeclType(CTSD).getAsOpaquePtr())); + + // User-defined records (even with "complex" in the name) are not builtins. + Interp->declare("class complex_number {}; class regular_record {};"); + EXPECT_FALSE( + Cpp::IsBuiltin(Cpp::GetTypeFromScope(Cpp::GetNamed("complex_number", nullptr)))); + EXPECT_FALSE( + Cpp::IsBuiltin(Cpp::GetTypeFromScope(Cpp::GetNamed("regular_record", nullptr)))); } TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IsTemplate) { @@ -557,10 +559,6 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_GetScopefromCompleteName) { } TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_GetNamed) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; -#endif std::string code = R"(namespace N1 { namespace N2 { class C { @@ -928,11 +926,7 @@ template constexpr T pi = T(3.1415926535897932385L); auto* VD = cast((Decl*)Instance1); VarTemplateDecl* VDTD1 = VD->getSpecializedTemplate(); EXPECT_TRUE(VDTD1->isThisDeclarationADefinition()); -#if CLANG_VERSION_MAJOR == 18 - TemplateArgument TA1 = (*VD->getTemplateArgsInfo())[0].getArgument(); -#else TemplateArgument TA1 = (*VD->getTemplateArgsAsWritten())[0].getArgument(); -#endif // CLANG_VERSION_MAJOR EXPECT_TRUE(TA1.getAsType()->isIntegerType()); } @@ -959,10 +953,6 @@ template T TrivialFnTemplate() { return T(); } TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_InstantiateTemplateFunctionFromString) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; -#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; std::vector interpreter_args = {"-include", "new"}; @@ -1107,10 +1097,6 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, } TYPED_TEST(CPPINTEROP_TEST_MODE, ScopeReflection_IncludeVector) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; -#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; std::string code = R"( diff --git a/interpreter/CppInterOp/unittests/CppInterOp/TestSharedLib/CMakeLists.txt b/interpreter/CppInterOp/unittests/CppInterOp/TestSharedLib/CMakeLists.txt index 477b2fc225029..2c237614d40a9 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/TestSharedLib/CMakeLists.txt +++ b/interpreter/CppInterOp/unittests/CppInterOp/TestSharedLib/CMakeLists.txt @@ -11,9 +11,6 @@ set_output_directory(TestSharedLib if (EMSCRIPTEN) - set_target_properties(TestSharedLib - PROPERTIES NO_SONAME 1 - ) target_compile_options(TestSharedLib PUBLIC "SHELL: ${CPPINTEROP_EXTRA_WASM_FLAGS}" ) diff --git a/interpreter/CppInterOp/unittests/CppInterOp/TypeReflectionTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/TypeReflectionTest.cpp index 9a85b8fa88d88..9ad3d534a72a5 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/TypeReflectionTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/TypeReflectionTest.cpp @@ -380,19 +380,23 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, TypeReflection_GetComplexType) { } TYPED_TEST(CPPINTEROP_TEST_MODE, TypeReflection_GetTypeFromScope) { - std::vector Decls; + std::vector Decls, SubDecls; - std::string code = R"( + std::string code = R"( + namespace N { class C {}; struct S {}; int a = 10; + } )"; GetAllTopLevelDecls(code, Decls); + EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(Decls[0])), "NULL TYPE"); - EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(Decls[0])), "C"); - EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(Decls[1])), "S"); - EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(Decls[2])), "int"); + GetAllSubDecls(Decls[0], SubDecls); + EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(SubDecls[0])), "N::C"); + EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(SubDecls[1])), "N::S"); + EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(SubDecls[2])), "int"); EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetTypeFromScope(nullptr)), "NULL TYPE"); } @@ -551,9 +555,8 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, TypeReflection_IsPODType) { } TYPED_TEST(CPPINTEROP_TEST_MODE, TypeReflection_IsSmartPtrType) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && defined(_WIN32) + GTEST_SKIP() << "Test fails with Cling on Windows"; #endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; diff --git a/interpreter/CppInterOp/unittests/CppInterOp/Utils.cpp b/interpreter/CppInterOp/unittests/CppInterOp/Utils.cpp index d603737da36f2..57489ae0ad03a 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/Utils.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/Utils.cpp @@ -29,14 +29,18 @@ struct DispatchInitializer { std::abort(); } } - ~DispatchInitializer() { Cpp::UnloadDispatchAPI(); } + ~DispatchInitializer() = default; DispatchInitializer(const DispatchInitializer&) = delete; DispatchInitializer& operator=(const DispatchInitializer&) = delete; DispatchInitializer(DispatchInitializer&&) noexcept = default; DispatchInitializer& operator=(DispatchInitializer&&) noexcept = default; }; -// FIXME: Make this threadsafe by moving it as a function static. -DispatchInitializer g_dispatch_init; +// Thread-safe initialization using function-local static +DispatchInitializer& GetDispatchInitializer() { + static DispatchInitializer instance; + return instance; +} +const DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); } // namespace #endif diff --git a/interpreter/CppInterOp/unittests/CppInterOp/VariableReflectionTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/VariableReflectionTest.cpp index 9dc346da47f26..d98182031e1f1 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/VariableReflectionTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/VariableReflectionTest.cpp @@ -114,6 +114,9 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, VariableReflection_GetDatamembers) { CODE TYPED_TEST(CPPINTEROP_TEST_MODE, VariableReflection_DatamembersWithAnonymousStructOrUnion) { +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && defined(_WIN32) + GTEST_SKIP() << "Test fails with Cling on Windows"; +#endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; @@ -381,12 +384,11 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, VariableReflection_GetVariableOffset) { CODE TYPED_TEST(CPPINTEROP_TEST_MODE, VariableReflection_VariableOffsetsWithInheritance) { -#if CLANG_VERSION_MAJOR == 18 && defined(CPPINTEROP_USE_CLING) && \ - defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) - GTEST_SKIP() << "Test fails with Cling on Windows on ARM"; -#endif #ifdef __EMSCRIPTEN__ GTEST_SKIP() << "This test crashes for Emscripten builds of CppInterOp"; +#endif +#if CLANG_VERSION_MAJOR == 20 && defined(CPPINTEROP_USE_CLING) && defined(_WIN32) + GTEST_SKIP() << "Test fails with Cling on Windows"; #endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; diff --git a/interpreter/cling/include/cling/std.modulemap b/interpreter/cling/include/cling/std.modulemap index 2db4cc7c82181..8ac5dbf21a46e 100644 --- a/interpreter/cling/include/cling/std.modulemap +++ b/interpreter/cling/include/cling/std.modulemap @@ -161,6 +161,11 @@ module "std" [system] { export * header "fstream" } + module "format" { + requires cplusplus20 + export * + header "format" + } module "functional" { export * header "functional" diff --git a/interpreter/llvm-project/clang/include/clang/Serialization/ASTWriter.h b/interpreter/llvm-project/clang/include/clang/Serialization/ASTWriter.h index 079e39a9fb678..a3a78223d131c 100644 --- a/interpreter/llvm-project/clang/include/clang/Serialization/ASTWriter.h +++ b/interpreter/llvm-project/clang/include/clang/Serialization/ASTWriter.h @@ -586,8 +586,6 @@ class ASTWriter : public ASTDeserializationListener, void WriteTypeAbbrevs(); void WriteType(ASTContext &Context, QualType T); - bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC); - void GenerateSpecializationInfoLookupTable( const NamedDecl *D, llvm::SmallVectorImpl &Specializations, llvm::SmallVectorImpl &LookupTable, bool IsPartial); diff --git a/interpreter/llvm-project/clang/lib/Serialization/ASTWriter.cpp b/interpreter/llvm-project/clang/lib/Serialization/ASTWriter.cpp index 4333f0b95b853..5ce05f741b516 100644 --- a/interpreter/llvm-project/clang/lib/Serialization/ASTWriter.cpp +++ b/interpreter/llvm-project/clang/lib/Serialization/ASTWriter.cpp @@ -4493,12 +4493,6 @@ uint64_t ASTWriter::WriteSpecializationInfoLookupTable( return Offset; } -bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, - DeclContext *DC) { - return Result.hasExternalDecls() && - DC->hasNeedToReconcileExternalVisibleStorage(); -} - /// Returns ture if all of the lookup result are either external, not emitted or /// predefined. In such cases, the lookup result is not interesting and we don't /// need to record the result in the current being written module. Return false @@ -4550,14 +4544,12 @@ void ASTWriter::GenerateNameLookupTable( // order. SmallVector Names; - // We also build up small sets of the constructor and conversion function - // names which are visible. - llvm::SmallPtrSet ConstructorNameSet, ConversionNameSet; - - for (auto &Lookup : *DC->buildLookup()) { - auto &Name = Lookup.first; - auto &Result = Lookup.second; + // We also track whether we're writing out the DeclarationNameKey for + // constructors or conversion functions. + bool IncludeConstructorNames = false; + bool IncludeConversionNames = false; + for (auto &[Name, Result] : *DC->buildLookup()) { // If there are no local declarations in our lookup result, we // don't need to write an entry for the name at all. If we can't // write out a lookup set without performing more deserialization, @@ -4566,15 +4558,8 @@ void ASTWriter::GenerateNameLookupTable( // Also in reduced BMI, we'd like to avoid writing unreachable // declarations in GMF, so we need to avoid writing declarations // that entirely external or unreachable. - // - // FIMXE: It looks sufficient to test - // isLookupResultNotInteresting here. But due to bug we have - // to test isLookupResultExternal here. See - // https://github.com/llvm/llvm-project/issues/61065 for details. - if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) && - isLookupResultNotInteresting(*this, Result)) + if (GeneratingReducedBMI && isLookupResultNotInteresting(*this, Result)) continue; - // We also skip empty results. If any of the results could be external and // the currently available results are empty, then all of the results are // external and we skip it above. So the only way we get here with an empty @@ -4589,24 +4574,20 @@ void ASTWriter::GenerateNameLookupTable( // results for them. This in almost certainly a bug in Clang's name lookup, // but that is likely to be hard or impossible to fix and so we tolerate it // here by omitting lookups with empty results. - if (Lookup.second.getLookupResult().empty()) + if (Result.getLookupResult().empty()) continue; - switch (Lookup.first.getNameKind()) { + switch (Name.getNameKind()) { default: - Names.push_back(Lookup.first); + Names.push_back(Name); break; case DeclarationName::CXXConstructorName: - assert(isa(DC) && - "Cannot have a constructor name outside of a class!"); - ConstructorNameSet.insert(Name); + IncludeConstructorNames = true; break; case DeclarationName::CXXConversionFunctionName: - assert(isa(DC) && - "Cannot have a conversion function name outside of a class!"); - ConversionNameSet.insert(Name); + IncludeConversionNames = true; break; } } @@ -4614,57 +4595,34 @@ void ASTWriter::GenerateNameLookupTable( // Sort the names into a stable order. llvm::sort(Names); - if (auto *D = dyn_cast(DC)) { + if (IncludeConstructorNames || IncludeConversionNames) { // We need to establish an ordering of constructor and conversion function - // names, and they don't have an intrinsic ordering. - - // First we try the easy case by forming the current context's constructor - // name and adding that name first. This is a very useful optimization to - // avoid walking the lexical declarations in many cases, and it also - // handles the only case where a constructor name can come from some other - // lexical context -- when that name is an implicit constructor merged from - // another declaration in the redecl chain. Any non-implicit constructor or - // conversion function which doesn't occur in all the lexical contexts - // would be an ODR violation. - auto ImplicitCtorName = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Context.getRecordType(D))); - if (ConstructorNameSet.erase(ImplicitCtorName)) - Names.push_back(ImplicitCtorName); - - // If we still have constructors or conversion functions, we walk all the - // names in the decl and add the constructors and conversion functions - // which are visible in the order they lexically occur within the context. - if (!ConstructorNameSet.empty() || !ConversionNameSet.empty()) - for (Decl *ChildD : cast(DC)->decls()) - if (auto *ChildND = dyn_cast(ChildD)) { - auto Name = ChildND->getDeclName(); - switch (Name.getNameKind()) { - default: - continue; - - case DeclarationName::CXXConstructorName: - if (ConstructorNameSet.erase(Name)) - Names.push_back(Name); - break; + // names, and they don't have an intrinsic ordering. We also need to write + // out all constructor and conversion function results if we write out any + // of them, because they're all tracked under the same lookup key. + llvm::SmallPtrSet AddedNames; + for (Decl *ChildD : cast(DC)->decls()) { + if (auto *ChildND = dyn_cast(ChildD)) { + auto Name = ChildND->getDeclName(); + switch (Name.getNameKind()) { + default: + continue; - case DeclarationName::CXXConversionFunctionName: - if (ConversionNameSet.erase(Name)) - Names.push_back(Name); - break; - } + case DeclarationName::CXXConstructorName: + if (!IncludeConstructorNames) + continue; + break; - if (ConstructorNameSet.empty() && ConversionNameSet.empty()) - break; + case DeclarationName::CXXConversionFunctionName: + if (!IncludeConversionNames) + continue; + break; } - - assert(ConstructorNameSet.empty() && "Failed to find all of the visible " - "constructors by walking all the " - "lexical members of the context."); - assert(ConversionNameSet.empty() && "Failed to find all of the visible " - "conversion functions by walking all " - "the lexical members of the context."); + if (AddedNames.insert(Name).second) + Names.push_back(Name); + } + } } - // Next we need to do a lookup with each name into this decl context to fully // populate any results from external sources. We don't actually use the // results of these lookups because we only want to use the results after all diff --git a/interpreter/llvm-project/llvm-project.tag b/interpreter/llvm-project/llvm-project.tag index 7671eec8bada7..d8f26d75d936d 100644 --- a/interpreter/llvm-project/llvm-project.tag +++ b/interpreter/llvm-project/llvm-project.tag @@ -1 +1 @@ -ROOT-llvm20-20260223-01 +ROOT-llvm20-20260408-01 diff --git a/io/io/inc/ROOT/RFile.hxx b/io/io/inc/ROOT/RFile.hxx index 445cfba08e6c3..27871c85aae0e 100644 --- a/io/io/inc/ROOT/RFile.hxx +++ b/io/io/inc/ROOT/RFile.hxx @@ -2,7 +2,7 @@ /// \ingroup Base ROOT7 /// \author Giacomo Parolini /// \date 2025-03-19 -/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback +/// \warning This is part of the ROOT 7 prototype! It will change without notice. Feedback /// is welcome! #ifndef ROOT7_RFile @@ -189,6 +189,9 @@ public: \ingroup RFile \brief An interface to read from, or write to, a ROOT file, as well as performing other common operations. +Please refer to the documentation of TFile for the details related to how data and executable code can be stored +in ROOT files. + ## When and why should you use RFile RFile is a modern and minimalistic interface to ROOT files, both local and remote, that can be used instead of TFile diff --git a/io/io/inc/ROOT/RRawFile.hxx b/io/io/inc/ROOT/RRawFile.hxx index 4aa54a787a031..1e1b83aca697d 100644 --- a/io/io/inc/ROOT/RRawFile.hxx +++ b/io/io/inc/ROOT/RRawFile.hxx @@ -140,6 +140,9 @@ protected: /// By default implemented as a loop of ReadAt calls but can be overwritten, e.g. XRootD or DAVIX implementations virtual void ReadVImpl(RIOVec *ioVec, unsigned int nReq); + // Default implementation: no-op + virtual void SetDiscourageReadAheadImpl(bool /* value */) {} + /// Open the file if not already open. Otherwise noop. void EnsureOpen(); @@ -178,8 +181,9 @@ public: /// Returns the limits regarding the ioVec input to ReadV for this specific file; may open the file as a side-effect. virtual RIOVecLimits GetReadVLimits() { return RIOVecLimits(); } - /// Turn off buffered reads; all scalar read requests go directly to the implementation. Buffering can be turned - /// back on. + /// Turn on/off buffered reads; if off, all scalar read requests go directly to the implementation. Buffering also + /// turns on and off OS read-ahead where supported: if buffering is switched, SetDiscourageReadAheadImpl() will be + /// called accordingly. void SetBuffering(bool value); bool IsBuffering() const { return fIsBuffering; } diff --git a/io/io/inc/ROOT/RRawFileUnix.hxx b/io/io/inc/ROOT/RRawFileUnix.hxx index 822ef986cadf7..bb8ebb32fe2aa 100644 --- a/io/io/inc/ROOT/RRawFileUnix.hxx +++ b/io/io/inc/ROOT/RRawFileUnix.hxx @@ -37,6 +37,7 @@ protected: size_t ReadAtImpl(void *buffer, size_t nbytes, std::uint64_t offset) final; void ReadVImpl(RIOVec *ioVec, unsigned int nReq) final; std::uint64_t GetSizeImpl() final; + void SetDiscourageReadAheadImpl(bool value) final; public: RRawFileUnix(std::string_view url, RRawFile::ROptions options); diff --git a/io/io/inc/TBufferFile.h b/io/io/inc/TBufferFile.h index 5aaf5f1916f83..d581220c2439e 100644 --- a/io/io/inc/TBufferFile.h +++ b/io/io/inc/TBufferFile.h @@ -64,6 +64,7 @@ class TBufferFile : public TBufferIO { UInt_t CheckObject(UInt_t offset, const TClass *cl, Bool_t readClass = kFALSE); void WriteObjectClass(const void *actualObjStart, const TClass *actualClass, Bool_t cacheReuse) override; + bool ShouldNotReadCollection(Int_t lengthInBytes, Int_t nElements=1) const; public: enum { kStreamedMemberWise = BIT(14) }; //added to version number to know if a collection has been stored member-wise @@ -268,6 +269,16 @@ class TBufferFile : public TBufferIO { //---------------------- TBufferFile inlines --------------------------------------- +//______________________________________________________________________________ +inline bool TBufferFile::ShouldNotReadCollection(Int_t lengthInBytes, Int_t nElements) const +{ + // Three cases here in which we should not read the collection: + // 1. The collection has zero or a negative number of elements or + // 2. The length in bytes of the collection is zero or negative + // 3. The remaining part of the buffer is too short to read the collection + return nElements <= 0 || lengthInBytes <= 0 || (size_t)lengthInBytes > (size_t)(fBufMax - fBufCur); +} + //______________________________________________________________________________ inline void TBufferFile::WriteBool(Bool_t b) { diff --git a/io/io/inc/TEmulatedCollectionProxy.h b/io/io/inc/TEmulatedCollectionProxy.h index 3f1a1cd75dff4..eae8404029eac 100644 --- a/io/io/inc/TEmulatedCollectionProxy.h +++ b/io/io/inc/TEmulatedCollectionProxy.h @@ -12,7 +12,9 @@ #define ROOT_TEmulatedCollectionProxy #include "TGenCollectionProxy.h" +#include "ROOT/RAlignmentUtils.hxx" +#include #include class TEmulatedCollectionProxy : public TGenCollectionProxy { @@ -21,10 +23,90 @@ class TEmulatedCollectionProxy : public TGenCollectionProxy { friend class TCollectionProxy; public: - // Container type definition - typedef std::vector Cont_t; - // Pointer to container type - typedef Cont_t *PCont_t; + /// Storage type whose alignment matches \a Align bytes. + /// Used to instantiate std::vector specializations with guaranteed buffer alignment. + template + struct alignas(Align) AlignedStorage { + char data[Align] = {}; + }; + + // Convenience vector aliases for each supported alignment. + using Cont1_t = std::vector>; + using Cont2_t = std::vector>; + using Cont4_t = std::vector>; + using Cont8_t = std::vector>; + using Cont16_t = std::vector>; + using Cont32_t = std::vector>; + using Cont64_t = std::vector>; + using Cont128_t = std::vector>; + using Cont256_t = std::vector>; + using Cont512_t = std::vector>; + using Cont1024_t = std::vector>; + using Cont2048_t = std::vector>; + using Cont4096_t = std::vector>; + + // Canonical container type (used for sizeof/typeid; actual alignment is + // selected at runtime via the alignment switch in each method). + using Cont_t = std::vector; + using PCont_t = Cont_t *; + + /// Invoke \a fn(typed_ptr, elemSize) where typed_ptr is the container + /// pointer cast to the correct AlignedStorage* for the value class + /// alignment. \a fn receives the element size (N) as a second argument + /// so it can convert byte counts to element counts. + template + void WithCont(void *obj, F &&fn) const + { + auto *vcl = GetValueClass(); + std::size_t align = alignof(std::max_align_t); + if (!fKey && (fVal->fCase & kIsPointer)) { + // If the collection contains pointers, we need to use the alignment of a pointer, not of the value class. + align = alignof(void*); + } else if (vcl) { + assert(ROOT::Internal::IsValidAlignment(vcl->GetClassAlignment())); + align = vcl->GetClassAlignment(); + } else { + switch( int(fVal->fKind) ) { + case kChar_t: + case kUChar_t: align = alignof(char); break; + case kShort_t: + case kUShort_t: align = alignof(short); break; + case kInt_t: + case kUInt_t: align = alignof(int); break; + case kLong_t: + case kULong_t: align = alignof(long); break; + case kLong64_t: + case kULong64_t:align = alignof(long long); break; + case kFloat16_t: + case kFloat_t: align = alignof(float); break; + case kDouble32_t: + case kDouble_t: align = alignof(double); break; + default: + Fatal("TEmulatedCollectionProxy::WithCont", "Unsupported value type %d for value class %s", fVal->fKind, + vcl ? vcl->GetName() : ""); + } + } + switch (align) { + // When adding new cases here, also update the static_assert in TClingUtils.cxx + // to explicitly allow the new alignment and to update the error message accordingly. + case 4096: fn(reinterpret_cast(obj), std::size_t(4096)); break; + case 2048: fn(reinterpret_cast(obj), std::size_t(2048)); break; + case 1024: fn(reinterpret_cast(obj), std::size_t(1024)); break; + case 512: fn(reinterpret_cast(obj), std::size_t( 512)); break; + case 256: fn(reinterpret_cast(obj), std::size_t( 256)); break; + case 128: fn(reinterpret_cast(obj), std::size_t( 128)); break; + case 64: fn(reinterpret_cast(obj), std::size_t( 64)); break; + case 32: fn(reinterpret_cast(obj), std::size_t( 32)); break; + case 16: fn(reinterpret_cast(obj), std::size_t( 16)); break; + case 8: fn(reinterpret_cast(obj), std::size_t( 8)); break; + case 4: fn(reinterpret_cast(obj), std::size_t( 4)); break; + case 2: fn(reinterpret_cast(obj), std::size_t( 2)); break; + case 1: fn(reinterpret_cast(obj), std::size_t( 1)); break; + default: + Fatal("TEmulatedCollectionProxy::WithCont", "Unsupported alignment %zu for value class %s", + align, vcl ? vcl->GetName() : ""); + } + } protected: // Some hack to avoid const-ness @@ -59,28 +141,53 @@ class TEmulatedCollectionProxy : public TGenCollectionProxy { ~TEmulatedCollectionProxy() override; // Virtual constructor - void* New() const override { return new Cont_t; } + void *New() const override + { + void *mem = ::operator new(sizeof(Cont_t)); + WithCont(mem, [](auto *c, std::size_t) { new (c) std::decay_t(); }); + return mem; + } // Virtual in-place constructor - void* New(void* memory) const override { return new(memory) Cont_t; } + void *New(void *memory) const override + { + WithCont(memory, [](auto *c, std::size_t) { new (c) std::decay_t(); }); + return memory; + } // Virtual constructor - TClass::ObjectPtr NewObject() const override { return {new Cont_t, nullptr}; } + TClass::ObjectPtr NewObject() const override { return {New(), nullptr}; } // Virtual in-place constructor - TClass::ObjectPtr NewObject(void* memory) const override { return {new(memory) Cont_t, nullptr}; } + TClass::ObjectPtr NewObject(void *memory) const override { return {New(memory), nullptr}; } // Virtual array constructor - void* NewArray(Int_t nElements) const override { return new Cont_t[nElements]; } + void *NewArray(Int_t nElements) const override + { + void *arr = ::operator new(nElements * sizeof(Cont_t)); + for (Int_t i = 0; i < nElements; ++i) + WithCont(static_cast(arr) + i * sizeof(Cont_t), + [](auto *c, std::size_t) { new (c) std::decay_t(); }); + return arr; + } - // Virtual in-place constructor - void* NewArray(Int_t nElements, void* memory) const override { return new(memory) Cont_t[nElements]; } + // Virtual in-place array constructor + void *NewArray(Int_t nElements, void *memory) const override + { + for (Int_t i = 0; i < nElements; ++i) + WithCont(static_cast(memory) + i * sizeof(Cont_t), + [](auto *c, std::size_t) { new (c) std::decay_t(); }); + return memory; + } // Virtual array constructor - TClass::ObjectPtr NewObjectArray(Int_t nElements) const override { return {new Cont_t[nElements], nullptr}; } + TClass::ObjectPtr NewObjectArray(Int_t nElements) const override { return {NewArray(nElements), nullptr}; } - // Virtual in-place constructor - TClass::ObjectPtr NewObjectArray(Int_t nElements, void* memory) const override { return {new(memory) Cont_t[nElements], nullptr}; } + // Virtual in-place array constructor + TClass::ObjectPtr NewObjectArray(Int_t nElements, void *memory) const override + { + return {NewArray(nElements, memory), nullptr}; + } // Virtual destructor void Destructor(void* p, Bool_t dtorOnly = kFALSE) const override; @@ -130,4 +237,22 @@ class TEmulatedCollectionProxy : public TGenCollectionProxy { Bool_t IsValid() const; }; + +namespace ROOT::Internal::TEmulatedProxyHelpers { +inline void PrintWriteStlWithoutProxyMsg(const char *where, const char *clName, const char *BranchName) +{ + const char *writeStlWithoutProxyMsg = + "The class requested (%s) for the branch \"%s\" " + "is an instance of an stl collection and does not have a compiled CollectionProxy. " + "Please generate the dictionary for this collection (%s) to avoid writing corrupted data."; + // This error message is repeated several times in the code. We write it once. + Error(where, writeStlWithoutProxyMsg, clName, BranchName, clName); +} + +inline bool HasEmulatedProxy(TClass *cl){ + return cl && cl->GetCollectionProxy() && dynamic_cast(cl->GetCollectionProxy()); +} +} // namespace ROOT::Internal::TEmulatedProxyHelpers + + #endif diff --git a/io/io/inc/TGenCollectionProxy.h b/io/io/inc/TGenCollectionProxy.h index 310f8a1020bb0..da0cced70c750 100644 --- a/io/io/inc/TGenCollectionProxy.h +++ b/io/io/inc/TGenCollectionProxy.h @@ -17,11 +17,15 @@ #include "TCollectionProxyInfo.h" +#include "ROOT/RAlignmentUtils.hxx" + #include #include #include #include +#include #include +#include class TObjArray; class TCollectionProxyFactory; diff --git a/io/io/inc/TKey.h b/io/io/inc/TKey.h index ce15ab4c43981..75f27524ead31 100644 --- a/io/io/inc/TKey.h +++ b/io/io/inc/TKey.h @@ -39,7 +39,7 @@ class TKey : public TNamed { protected: Int_t fVersion; ///< Key version identifier - Int_t fNbytes; ///< Number of bytes for the object on file + Int_t fNbytes; ///< Number of bytes for the whole key on file (key header and data) Int_t fObjlen; ///< Length of uncompressed object in bytes TDatime fDatime; ///< Date/Time of insertion in file Short_t fKeylen; ///< Number of bytes for the key itself diff --git a/io/io/inc/TStreamerInfo.h b/io/io/inc/TStreamerInfo.h index a604a3cc196ea..ffe008fd308b0 100644 --- a/io/io/inc/TStreamerInfo.h +++ b/io/io/inc/TStreamerInfo.h @@ -90,6 +90,7 @@ class TStreamerInfo : public TVirtualStreamerInfo { Int_t fOnFileClassVersion;///> nch; if (nch > 0) { + if (nch == std::numeric_limits::max()) { + Error("ReadCharStar", "Cannot allocate buffer: maximum capacity exceeded (%d bytes)!", std::numeric_limits::max()); + return; + } s = new char[nch+1]; ReadFastArray(s, nch); s[nch] = 0; @@ -733,7 +737,7 @@ Int_t TBufferFile::ReadArray(Bool_t *&b) Int_t n; *this >> n; - if (n <= 0 || n > fBufSize) return 0; + if (ShouldNotReadCollection(n)) return 0; if (!b) b = new Bool_t[n]; @@ -762,7 +766,7 @@ Int_t TBufferFile::ReadArray(Char_t *&c) *this >> n; Int_t l = sizeof(Char_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!c) c = new Char_t[n]; @@ -785,7 +789,7 @@ Int_t TBufferFile::ReadArray(Short_t *&h) *this >> n; Int_t l = sizeof(Short_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!h) h = new Short_t[n]; @@ -818,7 +822,7 @@ Int_t TBufferFile::ReadArray(Int_t *&ii) *this >> n; Int_t l = sizeof(Int_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!ii) ii = new Int_t[n]; @@ -851,7 +855,7 @@ Int_t TBufferFile::ReadArray(Long_t *&ll) *this >> n; Int_t l = sizeof(Long_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!ll) ll = new Long_t[n]; @@ -877,7 +881,7 @@ Int_t TBufferFile::ReadArray(Long64_t *&ll) *this >> n; Int_t l = sizeof(Long64_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!ll) ll = new Long64_t[n]; @@ -905,7 +909,7 @@ Int_t TBufferFile::ReadArray(Float_t *&f) *this >> n; Int_t l = sizeof(Float_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!f) f = new Float_t[n]; @@ -938,7 +942,7 @@ Int_t TBufferFile::ReadArray(Double_t *&d) *this >> n; Int_t l = sizeof(Double_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!d) d = new Double_t[n]; @@ -966,7 +970,7 @@ Int_t TBufferFile::ReadArrayFloat16(Float_t *&f, TStreamerElement *ele) Int_t n; *this >> n; - if (n <= 0 || 3*n > fBufSize) return 0; + if (ShouldNotReadCollection(3*n, n)) return 0; if (!f) f = new Float_t[n]; @@ -988,7 +992,7 @@ Int_t TBufferFile::ReadArrayDouble32(Double_t *&d, TStreamerElement *ele) Int_t n; *this >> n; - if (n <= 0 || 3*n > fBufSize) return 0; + if (ShouldNotReadCollection(3*n, n)) return 0; if (!d) d = new Double_t[n]; @@ -1008,7 +1012,7 @@ Int_t TBufferFile::ReadStaticArray(Bool_t *b) Int_t n; *this >> n; - if (n <= 0 || n > fBufSize) return 0; + if (ShouldNotReadCollection(n)) return 0; if (!b) return 0; @@ -1036,7 +1040,7 @@ Int_t TBufferFile::ReadStaticArray(Char_t *c) *this >> n; Int_t l = sizeof(Char_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!c) return 0; @@ -1058,7 +1062,7 @@ Int_t TBufferFile::ReadStaticArray(Short_t *h) *this >> n; Int_t l = sizeof(Short_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!h) return 0; @@ -1090,7 +1094,7 @@ Int_t TBufferFile::ReadStaticArray(Int_t *ii) *this >> n; Int_t l = sizeof(Int_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!ii) return 0; @@ -1122,7 +1126,7 @@ Int_t TBufferFile::ReadStaticArray(Long_t *ll) *this >> n; Int_t l = sizeof(Long_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!ll) return 0; @@ -1147,7 +1151,7 @@ Int_t TBufferFile::ReadStaticArray(Long64_t *ll) *this >> n; Int_t l = sizeof(Long64_t)*n; - if (l <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!ll) return 0; @@ -1174,7 +1178,7 @@ Int_t TBufferFile::ReadStaticArray(Float_t *f) *this >> n; Int_t l = sizeof(Float_t)*n; - if (n <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!f) return 0; @@ -1206,7 +1210,7 @@ Int_t TBufferFile::ReadStaticArray(Double_t *d) *this >> n; Int_t l = sizeof(Double_t)*n; - if (n <= 0 || l > fBufSize) return 0; + if (ShouldNotReadCollection(l, n)) return 0; if (!d) return 0; @@ -1233,7 +1237,7 @@ Int_t TBufferFile::ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele) Int_t n; *this >> n; - if (n <= 0 || 3*n > fBufSize) return 0; + if (ShouldNotReadCollection(3*n, n)) return 0; if (!f) return 0; @@ -1254,7 +1258,7 @@ Int_t TBufferFile::ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele) Int_t n; *this >> n; - if (n <= 0 || 3*n > fBufSize) return 0; + if (ShouldNotReadCollection(3*n, n)) return 0; if (!d) return 0; @@ -1268,7 +1272,7 @@ Int_t TBufferFile::ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele) void TBufferFile::ReadFastArray(Bool_t *b, Int_t n) { - if (n <= 0 || n > fBufSize) return; + if (ShouldNotReadCollection(n)) return; if (sizeof(Bool_t) > 1) { for (int i = 0; i < n; i++) @@ -1285,7 +1289,7 @@ void TBufferFile::ReadFastArray(Bool_t *b, Int_t n) void TBufferFile::ReadFastArray(Char_t *c, Int_t n) { - if (n <= 0 || n > fBufSize) return; + if (ShouldNotReadCollection(n)) return; Int_t l = sizeof(Char_t)*n; memcpy(c, fBufCur, l); @@ -1306,7 +1310,7 @@ void TBufferFile::ReadFastArrayString(Char_t *c, Int_t n) *this >> len; } if (len) { - if (len <= 0 || len > fBufSize) return; + if (ShouldNotReadCollection(len)) return; Int_t blen = len; if (len >= n) len = n-1; @@ -1326,7 +1330,7 @@ void TBufferFile::ReadFastArrayString(Char_t *c, Int_t n) void TBufferFile::ReadFastArray(Short_t *h, Int_t n) { Int_t l = sizeof(Short_t)*n; - if (n <= 0 || l > fBufSize) return; + if (ShouldNotReadCollection(l, n)) return; #ifdef R__BYTESWAP # ifdef USE_BSWAPCPY @@ -1348,7 +1352,7 @@ void TBufferFile::ReadFastArray(Short_t *h, Int_t n) void TBufferFile::ReadFastArray(Int_t *ii, Int_t n) { Int_t l = sizeof(Int_t)*n; - if (l <= 0 || l > fBufSize) return; + if (ShouldNotReadCollection(l, n)) return; #ifdef R__BYTESWAP # ifdef USE_BSWAPCPY @@ -1370,7 +1374,7 @@ void TBufferFile::ReadFastArray(Int_t *ii, Int_t n) void TBufferFile::ReadFastArray(Long_t *ll, Int_t n) { Int_t l = sizeof(Long_t)*n; - if (l <= 0 || l > fBufSize) return; + if (ShouldNotReadCollection(l, n)) return; TFile *file = (TFile*)fParent; if (file && file->GetVersion() < 30006) { @@ -1386,7 +1390,7 @@ void TBufferFile::ReadFastArray(Long_t *ll, Int_t n) void TBufferFile::ReadFastArray(Long64_t *ll, Int_t n) { Int_t l = sizeof(Long64_t)*n; - if (l <= 0 || l > fBufSize) return; + if (ShouldNotReadCollection(l, n)) return; #ifdef R__BYTESWAP for (int i = 0; i < n; i++) @@ -1403,7 +1407,7 @@ void TBufferFile::ReadFastArray(Long64_t *ll, Int_t n) void TBufferFile::ReadFastArray(Float_t *f, Int_t n) { Int_t l = sizeof(Float_t)*n; - if (l <= 0 || l > fBufSize) return; + if (ShouldNotReadCollection(l, n)) return; #ifdef R__BYTESWAP # ifdef USE_BSWAPCPY @@ -1425,7 +1429,7 @@ void TBufferFile::ReadFastArray(Float_t *f, Int_t n) void TBufferFile::ReadFastArray(Double_t *d, Int_t n) { Int_t l = sizeof(Double_t)*n; - if (l <= 0 || l > fBufSize) return; + if (ShouldNotReadCollection(l, n)) return; #ifdef R__BYTESWAP for (int i = 0; i < n; i++) @@ -1442,7 +1446,7 @@ void TBufferFile::ReadFastArray(Double_t *d, Int_t n) void TBufferFile::ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *elem) { - if (n <= 0 || 3*n > fBufSize) return; + if (ShouldNotReadCollection(3*n, n)) return; // The parameter should be const, however we have not yet decided how to // transition the signature since the function is virtual. This ensures @@ -1488,7 +1492,7 @@ void TBufferFile::ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *el void TBufferFile::ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor, Double_t minvalue) { - if (n <= 0 || 3*n > fBufSize) return; + if (ShouldNotReadCollection(3*n, n)) return; //a range was specified. We read an integer and convert it back to a float for (int j=0;j < n; j++) { @@ -1502,7 +1506,7 @@ void TBufferFile::ReadFastArrayWithFactor(Float_t *ptr, Int_t n, Double_t factor void TBufferFile::ReadFastArrayWithNbits(Float_t *ptr, Int_t n, Int_t nbits) { - if (n <= 0 || 3*n > fBufSize) return; + if (ShouldNotReadCollection(3*n, n)) return; if (!nbits) nbits = 12; //we read the exponent and the truncated mantissa of the float @@ -1535,7 +1539,7 @@ void TBufferFile::ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement * // that the function does not inadvertently use non-const parts of // TStreamerElement. const TStreamerElement *ele = elem; - if (n <= 0 || 3*n > fBufSize) return; + if (ShouldNotReadCollection(3*n, n)) return; if (ele && ele->GetFactor() != 0) { //a range was specified. We read an integer and convert it back to a double. @@ -1583,7 +1587,7 @@ void TBufferFile::ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement * void TBufferFile::ReadFastArrayWithFactor(Double_t *d, Int_t n, Double_t factor, Double_t minvalue) { - if (n <= 0 || 3*n > fBufSize) return; + if (ShouldNotReadCollection(3*n, n)) return; //a range was specified. We read an integer and convert it back to a double. for (int j=0;j < n; j++) { @@ -1597,7 +1601,7 @@ void TBufferFile::ReadFastArrayWithFactor(Double_t *d, Int_t n, Double_t factor, void TBufferFile::ReadFastArrayWithNbits(Double_t *d, Int_t n, Int_t nbits) { - if (n <= 0 || 3*n > fBufSize) return; + if (ShouldNotReadCollection(3*n, n)) return; if (!nbits) { //we read a float and convert it to double @@ -2962,9 +2966,12 @@ Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass if (version<=1) { if (version <= 0) { if (cl) { - if (cl->GetClassVersion() != 0 + auto clversion = cl->GetClassVersion(); + if ((clversion != 0 // If v.cnt < 6 then we have a class with a version that used to be zero and so there is no checksum. - && (v.cnt && v.cnt >= 6) + && (v.cnt && v.cnt >= 6)) || + // ::WriteVersion for a foreign class (no ClassDef) but defining Class_Version() { return 0; } does write checksum. + (clversion == 0 && version == 0 && cl->IsForeign()) ) { UInt_t checksum = 0; //*this >> checksum; @@ -2974,11 +2981,11 @@ Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass return vinfo->TStreamerInfo::GetClassVersion(); // Try to get inlining. } else { // There are some cases (for example when the buffer was stored outside of - // a ROOT file) where we do not have a TStreamerInfo. If the checksum is + // a ROOT file) where we do not have a TStreamerInfo. If the checksum is // the one from the current class, we can still assume that we can read // the data so let use it. if (checksum==cl->GetCheckSum() || cl->MatchLegacyCheckSum(checksum)) { - version = cl->GetClassVersion(); + version = clversion; } else { if (fParent) { Error("ReadVersion", "Could not find the StreamerInfo with a checksum of 0x%x for the class \"%s\" in %s.", diff --git a/io/io/src/TEmulatedCollectionProxy.cxx b/io/io/src/TEmulatedCollectionProxy.cxx index 8b84e00c17b61..9fccbf7922cf5 100644 --- a/io/io/src/TEmulatedCollectionProxy.cxx +++ b/io/io/src/TEmulatedCollectionProxy.cxx @@ -47,8 +47,8 @@ TEmulatedCollectionProxy::TEmulatedCollectionProxy(const TEmulatedCollectionProx fProperties |= kIsEmulated; } -TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char* cl_name, Bool_t silent) - : TGenCollectionProxy(typeid(std::vector), sizeof(std::vector::iterator)) +TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char *cl_name, Bool_t silent) + : TGenCollectionProxy(typeid(Cont_t), sizeof(Cont_t::iterator)) { // Build a Streamer for a collection whose type is described by 'collectionClass'. @@ -88,9 +88,12 @@ void TEmulatedCollectionProxy::Destructor(void* p, Bool_t dtorOnly) const const_cast(this)->Clear("force"); } if (dtorOnly) { - ((Cont_t*)p)->~Cont_t(); + WithCont(p, [](auto *c, std::size_t) { + using Vec_t = std::decay_t; + c->~Vec_t(); + }); } else { - delete (Cont_t*) p; + WithCont(p, [](auto *c, std::size_t) { delete c; }); } } @@ -102,7 +105,7 @@ void TEmulatedCollectionProxy::DeleteArray(void* p, Bool_t dtorOnly) const // how many elements are in the array. Warning("DeleteArray", "Cannot properly delete emulated array of %s at %p, I don't know how many elements it has!", fClass->GetName(), p); if (!dtorOnly) { - delete[] (Cont_t*) p; + ::operator delete(p); } } @@ -133,13 +136,11 @@ TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx(Bool_t silent) // Note: an emulated collection proxy is never really associative // since under-neath is actually an array. - // std::cout << "Initialized " << typeid(*this).name() << ":" << fName << std::endl; - auto alignedSize = [](size_t in) { - constexpr size_t kSizeOfPtr = sizeof(void*); - return in + (kSizeOfPtr - in%kSizeOfPtr)%kSizeOfPtr; + auto alignedSize = [](size_t in, TClass *align_cl) { + size_t align = align_cl ? align_cl->GetClassAlignment() : alignof(std::max_align_t); + return in + (align - in % align) % align; }; - struct GenerateTemporaryTEnum - { + struct GenerateTemporaryTEnum { TEnum *fTemporaryTEnum = nullptr; GenerateTemporaryTEnum(UInt_t typecase, const std::string &enumname) @@ -195,10 +196,10 @@ TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx(Bool_t silent) fProperties |= kNeedDelete; } if ( 0 == fValOffset ) { - fValOffset = alignedSize(fKey->fSize); + fValOffset = alignedSize(fKey->fSize, (*fValue).fType.GetClass()); } if ( 0 == fValDiff ) { - fValDiff = alignedSize(fValOffset + fVal->fSize); + fValDiff = alignedSize(fValOffset + fVal->fSize, (*fValue).fType.GetClass()); } if (num > 3 && !inside[3].empty()) { if (! TClassEdit::IsDefAlloc(inside[3].c_str(),inside[0].c_str())) { @@ -267,8 +268,7 @@ void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t force ) { // Shrink the container - typedef std::string String_t; - PCont_t c = PCont_t(fEnv->fObject); + typedef std::string String_t; char* addr = ((char*)fEnv->fStart) + fValDiff*left; size_t i; @@ -363,8 +363,11 @@ void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t force ) break; } } - c->resize(left*fValDiff,0); - fEnv->fStart = left > 0 ? c->data() : 0; + WithCont(fEnv->fObject, [&](auto *c, std::size_t alignmentElemSize) { + assert(fValDiff % alignmentElemSize == 0); + c->resize(left * fValDiff / alignmentElemSize); + fEnv->fStart = left > 0 ? c->data() : nullptr; + }); return; } @@ -372,10 +375,12 @@ void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left) { // Expand the container size_t i; - PCont_t c = PCont_t(fEnv->fObject); - c->resize(left*fValDiff,0); void *oldstart = fEnv->fStart; - fEnv->fStart = left > 0 ? c->data() : 0; + WithCont(fEnv->fObject, [&](auto *c, std::size_t alignmentElemSize) { + assert(fValDiff % alignmentElemSize == 0); + c->resize(left * fValDiff / alignmentElemSize); + fEnv->fStart = left > 0 ? c->data() : nullptr; + }); char* addr = ((char*)fEnv->fStart) + fValDiff*nCurr; switch ( fSTL_type ) { diff --git a/io/io/src/TFile.cxx b/io/io/src/TFile.cxx index 44f2c8a912bdb..459919ca42541 100644 --- a/io/io/src/TFile.cxx +++ b/io/io/src/TFile.cxx @@ -13,15 +13,35 @@ \file TFile.cxx \class TFile \ingroup IO -\brief A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-like logical structure, possibly including subdirectory hierarchies. +\brief A file, usually with extension .root, that stores data and code in the form of serialized objects in a +file-system-like logical structure, possibly including subdirectory hierarchies. +\note ROOT files contain data, and executable code, for example through TExec, TMacro, and TFormula instances. As for all files, **do not open ROOT files from an unknown origin!** \note See also \ref IO \note See also \ref rootio (or `io/doc/TFile` folder in your codebase) +ROOT files a are an efficient mean to store C++ class instances, e.g. data, +both as individual objects, in a so called *row-wise fashion*, and in a +*so-called columnar fashion*. Also executable code can be stored in ROOT files, +for example in the form of TMacro, TExec or TFormula instances, and the +related federation of classes. + +For example, a TCanvas or TPad instance may rely on TExec instances stored in +their *list of executables* to obtain certain graphics effects: in this case, +code will be executed upon drawing. A TH1 or a TGraph instance, as well as +their multidimensional counterparts and derived classes, may also execute code +upon drawing through TExec instances stored in their *list of functions*. +Another example of code which is executable is represented by TFormula +instances, that are the "computational workhorse" of function classes such as +TF1, its multidimensional counterparts, and related classes. There, jitted C++ +code is executed for example upon evaluation, for example during fits or +drawing operations, to obtain maximum runtime performance. + +
ROOT file data format specification A ROOT file is composed of a header, followed by consecutive data records -(`TKey` instances) with a well defined format. +(TKey instances) with a well defined format. The first data record starts at byte fBEGIN (currently set to kBEGIN). Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000 @@ -225,18 +245,18 @@ TFile::TFile() : TDirectoryFile(), fCompress(ROOT::RCompressionSetting::EAlgorit /// /// Option | Description /// -------|------------ -/// NEW or CREATE | Create a new file and open it for writing, if the file already exists the file is not opened. -/// RECREATE | Create a new file, if the file already exists it will be overwritten. -/// UPDATE | Open an existing file for writing. If no file exists, it is created. -/// READ | Open an existing file for reading (default). -/// NET | Used by derived remote file access classes, not a user callable option. -/// WEB | Used by derived remote http access class, not a user callable option. -/// READ_WITHOUT_GLOBALREGISTRATION | Used by TTreeProcessorMT, not a user callable option. +/// NEW or CREATE | Create a new file and open it for writing, if the file already exists the file +/// is not opened. RECREATE | Create a new file, if the file already exists it will be +/// overwritten. UPDATE | Open an existing file for writing. If no file exists, it is +/// created. READ | Open an existing file for reading (default). NET | Used by derived +/// remote file access classes, not a user callable option. WEB | Used by derived remote +/// http access class, not a user callable option. READ_WITHOUT_GLOBALREGISTRATION | Used by TTreeProcessorMT, not a +/// user callable option. /// /// If option = "" (default), READ is assumed. -/// \note Even in READ mode, if the file is the current directory `cd()`, and you create e.g. a new histogram in your code, -/// the histogram will be appended (but not written) to this directory, and automatically deleted when closing the file. -/// To avoid this behavior, call hist->SetDirectory(nullptr); after creating it. +/// \note Even in READ mode, if the file is the current directory `cd()`, and you create e.g. a new histogram in your +/// code, the histogram will be appended (but not written) to this directory, and automatically deleted when closing the +/// file. To avoid this behavior, call hist->SetDirectory(nullptr); after creating it. /// /// The file can be specified as a URL of the form: /// @@ -255,12 +275,12 @@ TFile::TFile() : TDirectoryFile(), fCompress(ROOT::RCompressionSetting::EAlgorit /// /// file.tar?filetype=raw /// -/// This is convenient because the many remote file access plugins allow -/// easy access to/from the many different mass storage systems. +/// This can be convenient because the many file access plugins allow +/// easy access to remote endpoints, e.g. mass storage pools. /// The title of the file (ftitle) will be shown by the ROOT browsers. /// A ROOT file (like a Unix file system) may contain objects and -/// directories. There are no restrictions for the number of levels -/// of directories. +/// directories, as well as executable code. There are no restrictions +/// for the number of levels of directories. /// A ROOT file is designed such that one can write in the file in pure /// sequential mode (case of BATCH jobs). In this case, the file may be /// read sequentially again without using the file index written @@ -288,7 +308,9 @@ TFile::TFile() : TDirectoryFile(), fCompress(ROOT::RCompressionSetting::EAlgorit /// The enumeration ROOT::RCompressionSetting::EAlgorithm associates each /// algorithm with a number. There is a utility function to help /// to set the value of compress. For example, +/// /// ROOT::CompressionSettings(ROOT::kLZMA, 1) +/// /// will build an integer which will set the compression to use /// the LZMA algorithm and compression level 1. These are defined /// in the header file Compression.h. @@ -315,7 +337,7 @@ TFile::TFile() : TDirectoryFile(), fCompress(ROOT::RCompressionSetting::EAlgorit /// } /// ~~~ /// When opening the file, the system checks the validity of this directory. -/// If something wrong is detected, an automatic Recovery is performed. In +/// If something wrong is detected, an automatic recovery is performed. In /// this case, the file is scanned sequentially reading all logical blocks /// and attempting to rebuild a correct directory (see TFile::Recover). /// One can disable the automatic recovery procedure when reading one diff --git a/io/io/src/TFileMerger.cxx b/io/io/src/TFileMerger.cxx index 270515168ed96..14c8d442575a2 100644 --- a/io/io/src/TFileMerger.cxx +++ b/io/io/src/TFileMerger.cxx @@ -78,7 +78,11 @@ static Int_t R__GetSystemMaxOpenedFiles() } #endif if (maxfiles > kClingFileNumber) { - return maxfiles - kClingFileNumber; + // Limit the maximum number of opened files to 128 to mitigate memory + // consumption issues that may arise during merges with many files. + // For further details see analysis at: + // https://github.com/root-project/root/issues/21660 + return std::min(128, maxfiles - kClingFileNumber); } else if (maxfiles > 5) { return maxfiles - 5; } else { @@ -661,6 +665,13 @@ Bool_t TFileMerger::MergeOne(TDirectory *target, TList *sourcelist, Int_t type, if (!hobj) { TKey *key2 = (TKey*)ndir->GetListOfKeys()->FindObject(keyname); if (key2) { + if (strcmp(key2->GetClassName(), keyclassname) != 0) { + Error("MergeRecursive", + "Object type mismatch for key '%s' in file '%s': expected '%s' but found '%s'.", keyname, + nextsource->GetName(), keyclassname, key2->GetClassName()); + nextsource = (TFile *)sourcelist->After(nextsource); + return kFALSE; + } hobj = key2->ReadObj(); if (!hobj) { switch (fErrBehavior) { diff --git a/io/io/src/TGenCollectionProxy.cxx b/io/io/src/TGenCollectionProxy.cxx index 3defdece6e7fd..bae962d6e7c95 100644 --- a/io/io/src/TGenCollectionProxy.cxx +++ b/io/io/src/TGenCollectionProxy.cxx @@ -1519,8 +1519,7 @@ void TGenCollectionProxy__VectorCreateIterators(void *obj, void **begin_arena, v return; } *begin_arena = vec->data(); - *end_arena = vec->data() + vec->size(); - + *end_arena = vec->data() + vec->size(); } //////////////////////////////////////////////////////////////////////////////// @@ -1624,7 +1623,9 @@ TVirtualCollectionProxy::CreateIterators_t TGenCollectionProxy::GetFunctionCreat // fprintf(stderr,"a generic iterator\n"); // TODO could we do better than SlowCreateIterators for RVec? - if (fSTL_type==ROOT::kSTLvector || (fProperties & kIsEmulated)) + if (fProperties & kIsEmulated) + return fFunctionCreateIterators = TGenCollectionProxy__VectorCreateIterators; + else if (fSTL_type == ROOT::kSTLvector) return fFunctionCreateIterators = TGenCollectionProxy__VectorCreateIterators; else if ( (fProperties & kIsAssociative) && read) return TGenCollectionProxy__StagingCreateIterators; diff --git a/io/io/src/TKey.cxx b/io/io/src/TKey.cxx index a7693c96a9e73..c59d0f71c8904 100644 --- a/io/io/src/TKey.cxx +++ b/io/io/src/TKey.cxx @@ -49,6 +49,7 @@ #include #include +#include #include "TROOT.h" #include "TClass.h" @@ -1214,12 +1215,44 @@ void TKey::ReadBuffer(char *&buffer) void TKey::ReadKeyBuffer(char *&buffer) { frombuf(buffer, &fNbytes); + if (fNbytes < 0) { + Error("ReadKeyBuffer", "The value of fNbytes is negative (%d): cannot continue to read the key buffer.", fNbytes); + MakeZombie(); + fNbytes = 0; + return; + } Version_t version; frombuf(buffer,&version); fVersion = (Int_t)version; frombuf(buffer, &fObjlen); + if (fObjlen < 0) { + Error("ReadKeyBuffer", "The value of fObjlen is negative (%d): cannot continue to read the key buffer.", fObjlen); + MakeZombie(); + fObjlen = 0; + return; + } fDatime.ReadBuffer(buffer); frombuf(buffer, &fKeylen); + if (fKeylen < 0) { + Error("ReadKeyBuffer", "The value of fKeylen is negative (%d): cannot continue to read the key buffer.", fKeylen); + MakeZombie(); + fKeylen = 0; + return; + } + + if (fNbytes < fKeylen) { + Error("ReadKeyBuffer", "fNbytes (%d) < fKeylen (%d): cannot continue to read the key buffer.", fNbytes, fKeylen); + MakeZombie(); + return; + } + + constexpr auto maxInt_t = std::numeric_limits::max(); + if (fKeylen > (maxInt_t - fObjlen)) { + Error("ReadKeyBuffer", "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.", fObjlen, fKeylen, maxInt_t); + MakeZombie(); + return; + } + frombuf(buffer, &fCycle); if (fVersion > 1000) { frombuf(buffer, &fSeekKey); diff --git a/io/io/src/TStreamerInfo.cxx b/io/io/src/TStreamerInfo.cxx index 3900b54b37cf8..0b23b352d9d28 100644 --- a/io/io/src/TStreamerInfo.cxx +++ b/io/io/src/TStreamerInfo.cxx @@ -74,9 +74,12 @@ element type. #include "TVirtualMutex.h" #include "TStreamerInfoActions.h" +#include "ROOT/RAlignmentUtils.hxx" #include +#include #include +#include std::atomic TStreamerInfo::fgCount{0}; @@ -154,6 +157,7 @@ TStreamerInfo::TStreamerInfo() fNfulldata= 0; fNslots = 0; fSize = 0; + fAlignment= 0; fClassVersion = 0; fOnFileClassVersion = 0; fOldVersion = Class()->GetClassVersion(); @@ -188,6 +192,7 @@ TStreamerInfo::TStreamerInfo(TClass *cl) fNfulldata= 0; fNslots = 0; fSize = 0; + fAlignment= 0; fClassVersion = fClass->GetClassVersion(); fOnFileClassVersion = 0; fOldVersion = Class()->GetClassVersion(); @@ -240,6 +245,28 @@ TStreamerInfo::~TStreamerInfo() /// Makes sure kBuildRunning reset once Build finishes. namespace { + using ROOT::Internal::AlignUp; + + /// Layout of the cookie header that NewArray writes before the data and + /// DeleteArray reads back. Both functions must use exactly this struct to + /// stay in sync; + /// The header holds two Long_t cookie values (size and nElements). + /// Round the header size up to the next multiple of 'align' so that + /// dataBegin (= p + headerSize) is itself aligned to 'align'. + struct ArrayCookieLayout { + std::size_t align; ///< Alignment of the class (and of the whole block). + std::size_t cookieSize; ///< Raw size of the two Long_t cookie fields. + std::size_t headerSize; ///< Padded header size (cookieSize rounded up to align). + + explicit ArrayCookieLayout(const TClass *cl) + : align(std::max(cl->GetClassAlignment(), alignof(Long_t))), + cookieSize(sizeof(Long_t) * 2), + headerSize(AlignUp(cookieSize, align)) + { + assert(ROOT::Internal::IsValidAlignment(align)); + } + }; + struct TPreventRecursiveBuildGuard { TPreventRecursiveBuildGuard(TStreamerInfo* info): fInfo(info) { fInfo->SetBit(TStreamerInfo::kBuildRunning); @@ -503,6 +530,11 @@ void TStreamerInfo::Build(Bool_t isTransient) } if (element) { fElements->Add(element); + // We are building the TStreamerInfo for the in-memory representation + // of a loaded class, so we don't need to cross check the element's + // alignment (fAlignment will eventually be set to the one provided + // to the dictionary). + fAlignment = std::max(fAlignment, element->GetAlignment()); } } // end of base class loop } @@ -800,6 +832,11 @@ void TStreamerInfo::Build(Bool_t isTransient) } fElements->Add(element); + // We are building the TStreamerInfo for the in-memory representation + // of a loaded class, so we don't need to cross check the element's + // alignment (fAlignment will eventually be set to the one provided + // to the dictionary). + fAlignment = std::max(fAlignment, element->GetAlignment()); } // end of member loop // Now add artificial TStreamerElement (i.e. rules that creates new members or set transient members). @@ -1912,8 +1949,6 @@ void TStreamerInfo::BuildOld() Int_t offset = 0; TMemberStreamer* streamer = 0; - constexpr size_t kSizeOfPtr = sizeof(void*); - int nBaze = 0; if ((fElements->GetEntriesFast() == 1) && !strcmp(fElements->At(0)->GetName(), "This")) { @@ -2026,6 +2061,7 @@ void TStreamerInfo::BuildOld() // Calculate the offset using the 'real' base class name (as opposed to the // '@@emulated' in the case of the emulation of an abstract base class. + // baseOffset already take alignment in consideration. Int_t baseOffset = fClass->GetBaseClassOffset(baseclass); // Deal with potential schema evolution (renaming) of the base class. @@ -2090,14 +2126,24 @@ void TStreamerInfo::BuildOld() fNVirtualInfoLoc += infobase->fNVirtualInfoLoc; } - - { - if (baseOffset < 0) { - element->SetNewType(TVirtualStreamerInfo::kNoType); + if (baseOffset < 0) { + element->SetNewType(TVirtualStreamerInfo::kNoType); + } else { + auto align = baseclass->GetClassAlignment(); + if (!ROOT::Internal::IsValidAlignment(align)) { + // Print error only if this is meant to be the 'current' + // class layout description. + if (fClass->GetClassVersion() == fClassVersion) { + Error("TStreamerInfo::BuildOld", "Cannot determine alignment for base class %s for element %s", + baseclass->GetName(), GetName()); + } + align = alignof(std::max_align_t); } + fAlignment = std::max(fAlignment, align); } element->SetOffset(baseOffset); - offset += baseclass->Size(); + // We might be treating the base classes out of memory order. + offset = std::max(offset, baseOffset + baseclass->Size()); continue; } else { @@ -2182,8 +2228,22 @@ void TStreamerInfo::BuildOld() element->SetNewType(TVirtualStreamerInfo::kNoType); continue; } + + auto align = element->GetAlignment(); + if (!ROOT::Internal::IsValidAlignment(align)) { + // Print error only if this is meant to be the 'current' + // class layout description. + if (fClass->GetClassVersion() == fClassVersion) { + Error("TStreamerInfo::BuildOld", "Cannot determine alignment for base class %s for element %s", + element->GetClassPointer()->GetName(), GetName()); + } + align = alignof(std::max_align_t); + } + fAlignment = std::max(fAlignment, align); + element->SetOffset(baseOffset); - offset += asize; + // We might be treating the base classes out of memory order. + offset = std::max(offset, baseOffset + asize); element->Init(this); continue; } // if element is of type TStreamerBase or not. @@ -2195,6 +2255,7 @@ void TStreamerInfo::BuildOld() fVirtualInfoLoc = new ULong_t[1]; // To allow for a single delete statement. fVirtualInfoLoc[0] = offset; offset += sizeof(TStreamerInfo*); + fAlignment = std::max(fAlignment, alignof(TStreamerInfo *)); } TDataMember* dm = 0; @@ -2311,6 +2372,20 @@ void TStreamerInfo::BuildOld() } } // Class corresponding to StreamerInfo is emulated or not. + { + auto align = element->GetAlignment(); + if (!ROOT::Internal::IsValidAlignment(align)) { + // Print error only if this is meant to be the 'current' + // class layout description. + if (fClass->GetClassVersion() == fClassVersion) { + Error("TStreamerInfo::BuildOld", "Cannot determine alignment for type %s for element %s", + element->GetTypeName(), GetName()); + } + align = alignof(std::max_align_t); + } + fAlignment = std::max(fAlignment, align); + } + // Now let's deal with Schema evolution Int_t newType = -1; TClassRef newClass; @@ -2640,12 +2715,15 @@ void TStreamerInfo::BuildOld() // Regular case asize = element->GetSize(); } - // align the non-basic data types (required on alpha and IRIX!!) - if ((offset % kSizeOfPtr) != 0) { - offset = offset - (offset % kSizeOfPtr) + kSizeOfPtr; - } + // Use the precise alignment of the element type, falling back to + // max_align_t for types whose alignment is not known. + // (e.g. forward declared classes, or classes with incomplete types info, etc..) + const std::size_t align = element->GetAlignment(); + assert(ROOT::Internal::IsValidAlignment(align)); + offset = (Int_t)AlignUp((std::size_t)offset, align); element->SetOffset(offset); offset += asize; + fAlignment = std::max(fAlignment, align); } if (!wasCompiled && rules) { @@ -2744,6 +2822,7 @@ void TStreamerInfo::BuildOld() // If we get here, this means that there no data member after the last base class // (or no base class at all). if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) { + offset = (Int_t)AlignUp((size_t)offset, alignof(TStreamerInfo *)); fNVirtualInfoLoc = 1; fVirtualInfoLoc = new ULong_t[1]; // To allow for a single delete statement. fVirtualInfoLoc[0] = offset; @@ -3314,10 +3393,18 @@ void TStreamerInfo::ComputeSize() if (this == fClass->GetCurrentStreamerInfo()) { if (fClass->GetState() >= TClass::kInterpreted || fClass->fIsSyntheticPair) { fSize = fClass->GetClassSize(); + fAlignment = fClass->GetClassAlignment(); return; } } + // Note for TStreamerInfo that do not represent the current in memory + // layout of the class (whether that layout is the compiled, interpreted + // or emulated), the size calculated below is fantasy since the last element + // of this StreamerInfo may or may not be the last one in the in-memory layout. + // However this is per se a non issue as this size will not be used for + // anything. + TStreamerElement *element = (TStreamerElement*)fElements->Last(); //faster and more precise to use last element offset +size //on 64 bit machines, offset may be forced to be a multiple of 8 bytes @@ -3326,12 +3413,23 @@ void TStreamerInfo::ComputeSize() fSize = fVirtualInfoLoc[0] + sizeof(TStreamerInfo*); } - // On some platform and in some case of layout non-basic data types needs - // to be aligned. So let's be on the safe side and align on the size of - // the pointers. (Question: is that the right thing on x32 ABI ?) - constexpr size_t kSizeOfPtr = sizeof(void*); - if ((fSize % kSizeOfPtr) != 0 && !fClass->IsSyntheticPair()) { - fSize = fSize - (fSize % kSizeOfPtr) + kSizeOfPtr; + if (fClass->GetCollectionProxy()) { + fAlignment = fClass->GetClassAlignment(); + } + + if (!fAlignment && fElements->IsEmpty()) { + // Empty class alignment is 1. + fAlignment = 1; + } + + // If we have no information use the default alignment. + if (!fAlignment) { + Error("ComputeSize", "No information on the alignment of class %s, using default alignment of %d bytes", + GetName(), (Int_t)alignof(std::max_align_t)); + fAlignment = alignof(std::max_align_t); + } + if ((fSize % fAlignment) != 0) { + fSize = (Int_t)AlignUp((size_t)fSize, fAlignment); } } @@ -4991,8 +5089,13 @@ void* TStreamerInfo::New(void *obj) TIter next(fElements); if (!p) { - // Allocate and initialize the memory block. - p = new char[fSize]; + // Allocate and initialize the memory block. Ensure the returned + // storage is aligned to the class alignment requirement. + auto align = fClass->GetClassAlignment(); + // Use aligned new (C++17). This will return memory aligned to + // 'align' and can be freed with the matching delete[]. + assert(ROOT::Internal::IsValidAlignment(align)); // align must be a power of 2 + p = static_cast(::operator new[](fSize, std::align_val_t(align))); memset(p, 0, fSize); } @@ -5145,23 +5248,30 @@ void* TStreamerInfo::NewArray(Long_t nElements, void *ary) char* p = (char*) ary; + // Determine the alignment requirement for the class. + const ArrayCookieLayout layout(fClass); + if (!p) { - Long_t len = nElements * size + sizeof(Long_t)*2; - p = new char[len]; + + Long_t len = nElements * size + layout.headerSize; + + // Allocate and initialize the memory block. Request alignment so + // that the raw block starts on an 'align'-boundary; combined with + // the rounded-up header this guarantees dataBegin is also aligned. + p = static_cast(::operator new[](len, std::align_val_t(layout.align))); memset(p, 0, len); } - // Store the array cookie - Long_t* r = (Long_t*) p; + Long_t* r = (Long_t*)(p + layout.headerSize - layout.cookieSize); r[0] = size; r[1] = nElements; - char* dataBegin = (char*) &r[2]; + char *dataBegin = p + layout.headerSize; // Do a placement new for each element. - p = dataBegin; + char *q = dataBegin; for (Long_t cnt = 0; cnt < nElements; ++cnt) { - New(p); - p += size; + New(q); + q += size; } // for nElements return dataBegin; @@ -5306,7 +5416,14 @@ void TStreamerInfo::DestructorImpl(void* obj, Bool_t dtorOnly) } // iter over elements if (!dtorOnly) { - delete[] p; + // Note: We rely on fClass->GetClassAlignment() being the same than we had + // on construction time. + // However it technically can change but there is no much we can sensibly do to detect it. eg. "allocate object, + // unload library, reload library, destruct object" (but in this case the 'unload' library is meant to/should also + // destruct the object (unload transaction) but this is not always possible) or "allocate emulated object, load + // library, destruct object". + assert(ROOT::Internal::IsValidAlignment(fClass->GetClassAlignment())); + ::operator delete[](p, std::align_val_t(fClass->GetClassAlignment())); } } @@ -5350,10 +5467,15 @@ void TStreamerInfo::DeleteArray(void* ary, Bool_t dtorOnly) //???FIX ME: What about varying length arrays? - Long_t* r = (Long_t*) ary; - Long_t arrayLen = r[-1]; - Long_t size = r[-2]; - char* memBegin = (char*) &r[-2]; + // Recover the cookie layout: the two Long_t values sit in the header + // block immediately before dataBegin, with the same alignment-based + // headerSize that NewArray used. + const ArrayCookieLayout layout(fClass); + + Long_t *r = (Long_t *)((char *)ary - layout.cookieSize); + Long_t arrayLen = r[1]; + Long_t size = r[0]; + char *memBegin = (char *)ary - layout.headerSize; char* p = ((char*) ary) + ((arrayLen - 1) * size); for (Long_t cnt = 0; cnt < arrayLen; ++cnt, p -= size) { @@ -5362,7 +5484,7 @@ void TStreamerInfo::DeleteArray(void* ary, Bool_t dtorOnly) } // for arrayItemSize if (!dtorOnly) { - delete[] memBegin; + ::operator delete[](memBegin, std::align_val_t(layout.align)); } } @@ -5910,7 +6032,8 @@ TStreamerInfo::GenExplicitClassStreamer( const ::ROOT::TCollectionProxyInfo &inf // // Utility functions // -static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const std::string &dmFull, Int_t offset, bool silent) +static TStreamerElement * +R__CreateEmulatedElement(const char *dmName, const std::string &dmFull, Int_t offset, bool silent, bool needAlign) { // Create a TStreamerElement for the type 'dmFull' and whose data member name is 'dmName'. @@ -5918,12 +6041,22 @@ static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const std: TString dmType( TClassEdit::ShortType(dmFull.c_str(),1) ); Bool_t dmIsPtr = (s1 != dmType); const char *dmTitle = "Emulation"; + // Over align the basic data types. + size_t align = alignof(std::max_align_t); + if (needAlign && offset % align != 0) + offset = (Int_t)AlignUp((size_t)offset, align); TDataType *dt = gROOT->GetType(dmType); if (dt && dt->GetType() > 0 ) { // found a basic type Int_t dsize,dtype; dtype = dt->GetType(); dsize = dt->Size(); + // Use the precise alignment for the basic type if available. + if (needAlign && dt->GetAlignOf()) { + align = dt->GetAlignOf(); + if (offset % align != 0) + offset = (Int_t)AlignUp((size_t)offset, align); + } if (dmIsPtr && dtype != kCharStar) { if (!silent) Error("Pair Emulation Building","%s is not yet supported in pair emulation", @@ -5969,6 +6102,10 @@ static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const std: } } // a class + assert(ROOT::Internal::IsValidAlignment(clm->GetClassAlignment())); + align = std::max(align, clm->GetClassAlignment()); + if (needAlign && ((offset % align) != 0)) + offset = (Int_t)AlignUp((size_t)offset, align); if (clm->IsTObject()) { return new TStreamerObject(dmName,dmTitle,offset,dmFull.c_str()); } else if(clm == TString::Class() && !dmIsPtr) { @@ -6012,24 +6149,22 @@ TVirtualStreamerInfo *TStreamerInfo::GenerateInfoForPair(const std::string &firs i->SetName(pname.c_str()); i->SetClass(nullptr); i->GetElements()->Delete(); - TStreamerElement *fel = R__CreateEmulatedElement("first", firstname, 0, silent); + TStreamerElement *fel = R__CreateEmulatedElement("first", firstname, 0, silent, /*needAlign=*/false); Int_t size = 0; if (fel) { - i->GetElements()->Add( fel ); - - size = fel->GetSize(); - Int_t sp = sizeof(void *); - //align the non-basic data types (required on alpha and IRIX!!) - if (size%sp != 0) size = size - size%sp + sp; + i->GetElements()->Add(fel); + i->fAlignment = std::max(i->fAlignment, fel->GetAlignment()); } else { delete i; return 0; } if (hint_pair_offset) size = hint_pair_offset; - TStreamerElement *second = R__CreateEmulatedElement("second", secondname, size, silent); + TStreamerElement *second = + R__CreateEmulatedElement("second", secondname, size, silent, /*needAlign=*/!hint_pair_offset); if (second) { - i->GetElements()->Add( second ); + i->GetElements()->Add(second); + i->fAlignment = std::max(i->fAlignment, second->GetAlignment()); } else { delete i; return 0; diff --git a/io/io/src/TStreamerInfoActions.cxx b/io/io/src/TStreamerInfoActions.cxx index 35f315029fce5..bebd784eacd7d 100644 --- a/io/io/src/TStreamerInfoActions.cxx +++ b/io/io/src/TStreamerInfoActions.cxx @@ -4198,6 +4198,7 @@ void TStreamerInfo::Compile() fCompFull = new TCompInfo*[1]; fCompOpt = new TCompInfo*[1]; fCompOpt[0] = fCompFull[0] = &(fComp[0]); + fAlignment = 1; SetIsCompiled(); return; } diff --git a/io/io/test/RRawFile.cxx b/io/io/test/RRawFile.cxx index 1857698d43c5a..3a861e1618856 100644 --- a/io/io/test/RRawFile.cxx +++ b/io/io/test/RRawFile.cxx @@ -15,6 +15,7 @@ class RRawFileMock : public RRawFile { public: std::string fContent; unsigned fNumReadAt; + bool fDiscourageReadAhead = false; RRawFileMock(const std::string &content, RRawFile::ROptions options) : RRawFile("", options), fContent(content), fNumReadAt(0) { } @@ -39,6 +40,8 @@ class RRawFileMock : public RRawFile { } std::uint64_t GetSizeImpl() final { return fContent.size(); } + + void SetDiscourageReadAheadImpl(bool val) final { fDiscourageReadAhead = val; } }; } // anonymous namespace @@ -272,3 +275,22 @@ TEST(RRawFileTFile, TFile) EXPECT_EQ(seek[2], 0); EXPECT_EQ(seek[3], 100); } + +TEST(RRawFile, Readahead) +{ + { + RRawFileMock mock("", ROOT::Internal::RRawFile::ROptions()); + (void)mock.GetSize(); + EXPECT_FALSE(mock.fDiscourageReadAhead); + } + + { + RRawFileMock mock("", ROOT::Internal::RRawFile::ROptions()); + mock.SetBuffering(false); + EXPECT_FALSE(mock.fDiscourageReadAhead); + (void)mock.GetSize(); + EXPECT_TRUE(mock.fDiscourageReadAhead); + mock.SetBuffering(true); + EXPECT_FALSE(mock.fDiscourageReadAhead); + } +} diff --git a/io/io/test/TBufferFileTests.cxx b/io/io/test/TBufferFileTests.cxx index 30a5704d412fe..891f4fcf0d06d 100644 --- a/io/io/test/TBufferFileTests.cxx +++ b/io/io/test/TBufferFileTests.cxx @@ -1,7 +1,10 @@ #include "gtest/gtest.h" #include "TBufferFile.h" +#include "TMemFile.h" #include "TClass.h" +#include "TInterpreter.h" +#include "TKey.h" #include #include @@ -26,3 +29,23 @@ TEST(TBufferFile, ROOT_8367) EXPECT_FLOAT_EQ(v2[6], 7.); EXPECT_EQ(v2.size(), 7); } + +// https://github.com/root-project/root/issues/19371 +#define MYSTRUCT0 struct MyS0 { static constexpr short Class_Version() { return 0; } }; +#define MYSTRUCT1 struct MyS1 { static constexpr short Class_Version() { return 1; } }; +MYSTRUCT0 +MYSTRUCT1 +#define TO_LITERAL(string) _QUOTE_(string) +TEST(TBufferFile, ForeignZeroVersionClass) +{ + gInterpreter->Declare(TO_LITERAL(MYSTRUCT0)); + gInterpreter->Declare(TO_LITERAL(MYSTRUCT1)); + MyS0 s0; + MyS1 s1; + TMemFile f("mem19371.root", "RECREATE"); + f.WriteObject(&s0, "s0"); + f.WriteObject(&s1, "s1"); + EXPECT_NE(f.Get("s0"), nullptr); // Before the fix, even if return was already not nullptr, this line was raising an Error thus test would fail with unexpected diagnostic + EXPECT_NE(f.Get("s1"), nullptr); + EXPECT_EQ(f.GetKey("s0")->GetObjlen(), 10); +} diff --git a/io/io/test/TFileMergerTests.cxx b/io/io/test/TFileMergerTests.cxx index b32c6e321c3af..db58eedb1a209 100644 --- a/io/io/test/TFileMergerTests.cxx +++ b/io/io/test/TFileMergerTests.cxx @@ -18,6 +18,8 @@ #include "gtest/gtest.h" +#include + static void CreateATuple(TMemFile &file, const char *name, double value) { auto mytree = new TTree(name, "A tree"); @@ -396,3 +398,45 @@ TEST(TFileMerger, MergeSelectiveTutorial) EXPECT_NE(file.Get("ntuple"), nullptr); } } + +TEST(TFileMerger, TypeMismatchErrorTObjectWithNonTObject) +{ + struct PathRAII { + std::string fPath; + PathRAII(const char *path) : fPath(path) {} + ~PathRAII() { std::remove(fPath.c_str()); } + }; + + PathRAII input1("ErrorIfTypeMismatch_input1.root"); + const auto objname{"myobj"}; + PathRAII input2("ErrorIfTypeMismatch_input2.root"); + PathRAII outputfile("ErrorIfTypeMismatch_output.root"); + + // Create two files with objects of different types, one must be a TObject-derived type and other a + // non-TObject-derived type + { + auto f = std::make_unique(input1.fPath.c_str(), "RECREATE"); + auto t = std::make_unique(objname, objname); + f->Write(); + } + + { + auto f = std::make_unique(input2.fPath.c_str(), "RECREATE"); + std::vector v{1, 2, 3}; + f->WriteObject(&v, objname); + } + + // Ensure that TFileMerger detects the type mismatch and errors out. + { + ROOT::TestSupport::CheckDiagsRAII diagRAII; + diagRAII.requiredDiag(kError, "TFileMerger::MergeRecursive", "expected 'TTree' but found 'vector'", + /*matchFullMessage*/ false); + diagRAII.requiredDiag(kError, "TFileMerger::Merge", "error during merge of your ROOT files"); + + TFileMerger fm; + fm.OutputFile(outputfile.fPath.c_str()); + fm.AddFile(input1.fPath.c_str(), /*cpProgress*/ false); + fm.AddFile(input2.fPath.c_str(), /*cpProgress*/ false); + fm.PartialMerge(); + } +} diff --git a/io/xml/inc/TXMLEngine.h b/io/xml/inc/TXMLEngine.h index 55e4b28d53875..f8afa4b5c1e8e 100644 --- a/io/xml/inc/TXMLEngine.h +++ b/io/xml/inc/TXMLEngine.h @@ -36,8 +36,9 @@ class TXMLEngine : public TObject { void OutputValue(char *value, TXMLOutputStream *out); void SaveNode(XMLNodePointer_t xmlnode, TXMLOutputStream *out, Int_t layout, Int_t level); XMLNodePointer_t ReadNode(XMLNodePointer_t xmlparent, TXMLInputStream *inp, Int_t &resvalue); - void DisplayError(Int_t error, Int_t linenumber); + void DisplayError(Int_t error, Int_t linenumber, Bool_t is_parse_file = kTRUE); XMLDocPointer_t ParseStream(TXMLInputStream *input); + static Bool_t VerifyFilePath(const char *fname); Bool_t fSkipComments; /// #include #include +#include struct SXmlAttr_t { @@ -168,7 +169,7 @@ class TXMLEntity : public TNamed { class TXMLInputStream { protected: - std::istream *fInp; + std::ifstream *fInp; const char *fInpStr; Int_t fInpStrLen; @@ -231,6 +232,16 @@ class TXMLInputStream { fBuf = nullptr; } + //////////////////////////////////////////////////////////////////////////// + /// return true when file stream is configured + + inline Bool_t IsFile() const { return fInp != nullptr; } + + //////////////////////////////////////////////////////////////////////////// + /// return true when file stream is open + + inline Bool_t IsFileOpen() const { return fInp && fInp->is_open(); } + //////////////////////////////////////////////////////////////////////////// /// return true if end of file is achieved @@ -1347,6 +1358,26 @@ XMLNodePointer_t TXMLEngine::DocGetRootElement(XMLDocPointer_t xmldoc) return GetChild(xmlnode, kTRUE); } +//////////////////////////////////////////////////////////////////////////////// +/// Checked that filename does not contains relative path below current directory +/// +/// Used to prevent access to files below current directory + +Bool_t TXMLEngine::VerifyFilePath(const char *fname) +{ + if (!fname || !*fname) + return kFALSE; + + std::filesystem::path rel = std::filesystem::proximate(fname, std::filesystem::current_path()); + + // absolute path not allowed + if (rel.is_absolute()) + return kFALSE; + + // relative path should not start with ".." + return rel.empty() || (*rel.begin() != ".."); +} + //////////////////////////////////////////////////////////////////////////////// /// Parses content of file and tries to produce xml structures. /// The maxbuf argument specifies the max size of the XML file to be @@ -1359,6 +1390,10 @@ XMLDocPointer_t TXMLEngine::ParseFile(const char *filename, Int_t maxbuf) if (maxbuf < 100000) maxbuf = 100000; TXMLInputStream inp(true, filename, maxbuf); + if (!inp.IsFileOpen()) { + Error("ParseFile", "Fail open XML file %s", filename); + return nullptr; + } return ParseStream(&inp); } @@ -1405,7 +1440,7 @@ XMLDocPointer_t TXMLEngine::ParseStream(TXMLInputStream *inp) } while (true); if (!success) { - DisplayError(resvalue, inp->CurrentLine()); + DisplayError(resvalue, inp->CurrentLine(), inp->IsFile()); FreeDoc(xmldoc); return nullptr; } @@ -1471,7 +1506,7 @@ XMLNodePointer_t TXMLEngine::ReadSingleNode(const char *src) XMLNodePointer_t xmlnode = ReadNode(nullptr, &inp, resvalue); if (resvalue <= 0) { - DisplayError(resvalue, inp.CurrentLine()); + DisplayError(resvalue, inp.CurrentLine(), kFALSE); FreeNode(xmlnode); return nullptr; } @@ -1864,6 +1899,10 @@ XMLNodePointer_t TXMLEngine::ReadNode(XMLNodePointer_t xmlparent, TXMLInputStrea AddNodeContent(xmlparent, lastentity, beg - lastentity); if (entity->IsSystem()) { + if (!VerifyFilePath(entity->GetTitle())) { + resvalue = -15; + return contnode; + } XMLDocPointer_t entitydoc = ParseFile(entity->GetTitle()); if (!entitydoc) { resvalue = -14; @@ -2219,27 +2258,29 @@ XMLNodePointer_t TXMLEngine::ReadNode(XMLNodePointer_t xmlparent, TXMLInputStrea //////////////////////////////////////////////////////////////////////////////// /// Displays xml parsing error -void TXMLEngine::DisplayError(Int_t error, Int_t linenumber) +void TXMLEngine::DisplayError(Int_t error, Int_t linenumber, Bool_t is_parse_file) { + const char *method = is_parse_file ? "ParseFile" : "ParseString"; switch (error) { - case -14: Error("ParseFile", "Error include external XML file at line %d", linenumber); break; - case -13: Error("ParseFile", "Error processing DTD part of XML file at line %d", linenumber); break; - case -12: Error("ParseFile", "DOCTYPE missing after symbol at line %d, for instance node", linenumber); + Error(method, "Node cannot be closed with > symbol at line %d, for instance node", linenumber); break; case -10: - Error("ParseFile", "Error in xml comments definition at line %d, must be ", linenumber); + Error(method, "Error in xml comments definition at line %d, must be ", linenumber); break; - case -9: Error("ParseFile", "Multiple namespace definitions not allowed, line %d", linenumber); break; - case -8: Error("ParseFile", "Invalid namespace specification, line %d", linenumber); break; - case -7: Error("ParseFile", "Invalid attribute value, line %d", linenumber); break; - case -6: Error("ParseFile", "Invalid identifier for node attribute, line %d", linenumber); break; - case -5: Error("ParseFile", "Mismatch between open and close nodes, line %d", linenumber); break; - case -4: Error("ParseFile", "Unexpected close node, line %d", linenumber); break; - case -3: Error("ParseFile", "Valid identifier for close node is missing, line %d", linenumber); break; - case -2: Error("ParseFile", "No multiple content entries allowed, line %d", linenumber); break; - case -1: Error("ParseFile", "Unexpected end of xml file"); break; - default: Error("ParseFile", "XML syntax error at line %d", linenumber); break; + case -9: Error(method, "Multiple namespace definitions not allowed, line %d", linenumber); break; + case -8: Error(method, "Invalid namespace specification, line %d", linenumber); break; + case -7: Error(method, "Invalid attribute value, line %d", linenumber); break; + case -6: Error(method, "Invalid identifier for node attribute, line %d", linenumber); break; + case -5: Error(method, "Mismatch between open and close nodes, line %d", linenumber); break; + case -4: Error(method, "Unexpected close node, line %d", linenumber); break; + case -3: Error(method, "Valid identifier for close node is missing, line %d", linenumber); break; + case -2: Error(method, "No multiple content entries allowed, line %d", linenumber); break; + case -1: Error(method, "Unexpected end of xml file"); break; + default: Error(method, "XML syntax error at line %d", linenumber); break; } } diff --git a/js/LICENSE b/js/LICENSE index b9aea0154d89e..a6d9f24717fe9 100644 --- a/js/LICENSE +++ b/js/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright � 2013-2025 JavaScript ROOT authors +Copyright � 2013-2026 JavaScript ROOT authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/js/build/jsroot.js b/js/build/jsroot.js index 293dfc20b5d68..2e524875bff20 100644 --- a/js/build/jsroot.js +++ b/js/build/jsroot.js @@ -14,7 +14,7 @@ const version_id = 'dev', /** @summary version date * @desc Release date in format day/month/year like '14/04/2022' */ -version_date = '7/11/2025', +version_date = '16/04/2026', /** @summary version id and date * @desc Produced by concatenation of {@link version_id} and {@link version_date} @@ -257,6 +257,8 @@ settings = { Render3DBatch: constants$1.Render3D.Default, /** @summary Way to embed 3D drawing in SVG, see {@link constants.Embed3D} for possible values */ Embed3D: constants$1.Embed3D.Default, + /** @summary Use `resvg-js` backend for converting SVGs in node.js */ + UseResvgJs: true, /** @summary Default canvas width */ CanvasWidth: 1200, /** @summary Default canvas height */ @@ -363,6 +365,10 @@ settings = { * @desc Allows to retry files reading if original URL fails * @private */ FilesRemap: { 'https://root.cern/': 'https://root-eos.web.cern.ch/' }, + /** @summary THttpServer read timeout in ms + * @desc Configures timeout for requests to THttpServer + * @default 0 */ + ServerTimeout: 0, /** @summary Configure xhr.withCredentials = true when submitting http requests from JSROOT */ WithCredentials: false, /** @summary Skip streamer infos from the GUI */ @@ -965,13 +971,22 @@ function findFunction(name) { /** @summary Method to create http request, without promise can be used only in browser environment * @private */ -function createHttpRequest(url, kind, user_accept_callback, user_reject_callback, use_promise) { +function createHttpRequest(url, kind, user_accept_callback, user_reject_callback, use_promise, tmout) { + function handle_error(xhr, message, code, abort_reason) { + if (!xhr.did_abort) { + xhr.did_abort = abort_reason || true; + xhr.abort(); + } + if (!xhr.did_error || abort_reason) + console.warn(message); + if (!xhr.did_error) { + xhr.did_error = true; + xhr.error_callback(Error(message), code); + } + } function configureXhr(xhr) { xhr.http_callback = isFunc(user_accept_callback) ? user_accept_callback.bind(xhr) : () => {}; - xhr.error_callback = isFunc(user_reject_callback) ? user_reject_callback.bind(xhr) : function(err) { - console.warn(err.message); - this.http_callback(null); - }.bind(xhr); + xhr.error_callback = isFunc(user_reject_callback) ? user_reject_callback.bind(xhr) : function() { this.http_callback(null); }; if (!kind) kind = 'buf'; @@ -1007,11 +1022,8 @@ function createHttpRequest(url, kind, user_accept_callback, user_reject_callback if (settings.HandleWrongHttpResponse && (method === 'GET') && isFunc(xhr.addEventListener)) { xhr.addEventListener('progress', function(oEvent) { - if (oEvent.lengthComputable && this.expected_size && (oEvent.loaded > this.expected_size)) { - this.did_abort = true; - this.abort(); - this.error_callback(Error(`Server sends more bytes ${oEvent.loaded} than expected ${this.expected_size}. Abort I/O operation`), 598); - } + if (oEvent.lengthComputable && this.expected_size && (oEvent.loaded > this.expected_size)) + handle_error(this, `Server sends more bytes ${oEvent.loaded} than expected ${this.expected_size}. Abort I/O operation`, 598); }.bind(xhr)); } @@ -1021,11 +1033,8 @@ function createHttpRequest(url, kind, user_accept_callback, user_reject_callback if ((this.readyState === 2) && this.expected_size) { const len = parseInt(this.getResponseHeader('Content-Length')); - if (Number.isInteger(len) && (len > this.expected_size) && !settings.HandleWrongHttpResponse) { - this.did_abort = 'large'; - this.abort(); - return this.error_callback(Error(`Server response size ${len} larger than expected ${this.expected_size}. Abort I/O operation`), 599); - } + if (Number.isInteger(len) && (len > this.expected_size) && !settings.HandleWrongHttpResponse) + return handle_error(this, `Server response size ${len} larger than expected ${this.expected_size}. Abort I/O operation`, 599, 'large'); } if (this.readyState !== 4) @@ -1034,11 +1043,11 @@ function createHttpRequest(url, kind, user_accept_callback, user_reject_callback if ((this.status !== 200) && (this.status !== 206) && !browser.qt6 && // in these special cases browsers not always set status !((this.status === 0) && ((url.indexOf('file://') === 0) || (url.indexOf('blob:') === 0)))) - return this.error_callback(Error(`Fail to load url ${url}`), this.status); + return handle_error(this, `Fail to load url ${url}`, this.status); if (this.nodejs_checkzip && (this.getResponseHeader('content-encoding') === 'gzip')) { // special handling of gzip JSON objects in Node.js - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(handle => { + return import('zlib').then(handle => { const res = handle.unzipSync(Buffer.from(this.response)), obj = JSON.parse(res); // zlib returns Buffer, use JSON to parse it return this.http_callback(parse$1(obj)); @@ -1079,13 +1088,18 @@ function createHttpRequest(url, kind, user_accept_callback, user_reject_callback xhr.responseType = 'arraybuffer'; } + if (tmout && Number.isFinite(tmout)) { + xhr.timeout = tmout; + xhr.ontimeout = function() { handle_error(this, `Request ${url} timeout set ${tmout} ms`, 600, 'timeout'); }; + } + return xhr; } if (isNodeJs()) { if (!use_promise) throw Error('Not allowed to create http requests in node.js without promise'); - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(h => configureXhr(new h.default())); + return import('xhr2').then(h => configureXhr(new h.default())); } const xhr = configureXhr(new XMLHttpRequest()); @@ -1125,9 +1139,9 @@ async function httpRequest(url, kind, post_data) { async function injectCode(code) { if (nodejs) { let name, fs; - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(tmp => { + return import('tmp').then(tmp => { name = tmp.tmpNameSync() + '.js'; - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }); + return import('fs'); }).then(_fs => { fs = _fs; fs.writeFileSync(name, code); @@ -1210,7 +1224,7 @@ async function loadScript(url) { // local files, read and use it if (url.indexOf('./') === 0) - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(fs => injectCode(fs.readFileSync(url))); + return import('fs').then(fs => injectCode(fs.readFileSync(url))); return import(/* webpackIgnore: true */ url); } @@ -2911,11 +2925,11 @@ function compareValue(compare) { }; } -function chord() { - return chord$1(false); +function chord_default() { + return chord(false); } -function chord$1(directed, transpose) { +function chord(directed, transpose) { var padAngle = 0, sortGroups = null, sortSubgroups = null, @@ -3266,7 +3280,7 @@ function ribbon(headRadius) { return ribbon; } -function ribbon$1() { +function ribbon_default() { return ribbon(); } @@ -5174,8 +5188,8 @@ function formatDecimal(x) { // significant digits p, where x is positive and p is in [1, 21] or undefined. // For example, formatDecimalParts(1.23) returns ["123", 0]. function formatDecimalParts(x, p) { - if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity - var i, coefficient = x.slice(0, i); + if (!isFinite(x) || x === 0) return null; // NaN, ±Infinity, ±0 + var i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e"), coefficient = x.slice(0, i); // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). @@ -5280,7 +5294,7 @@ var prefixExponent; function formatPrefixAuto(x, p) { var d = formatDecimalParts(x, p); - if (!d) return x + ""; + if (!d) return prefixExponent = undefined, x.toPrecision(p); var coefficient = d[0], exponent = d[1], i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, @@ -5334,7 +5348,7 @@ function formatLocale$1(locale) { minus = locale.minus === undefined ? "−" : locale.minus + "", nan = locale.nan === undefined ? "NaN" : locale.nan + ""; - function newFormat(specifier) { + function newFormat(specifier, options) { specifier = formatSpecifier(specifier); var fill = specifier.fill, @@ -5359,8 +5373,8 @@ function formatLocale$1(locale) { // Compute the prefix and suffix. // For SI-prefix, the suffix is lazily computed. - var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", - suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; + var prefix = (options && options.prefix !== undefined ? options.prefix : "") + (symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : ""), + suffix = (symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "") + (options && options.suffix !== undefined ? options.suffix : ""); // What format function should we use? // Is this an integer type? @@ -5401,7 +5415,7 @@ function formatLocale$1(locale) { // Compute the prefix and suffix. valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; - valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); + valueSuffix = (type === "s" && !isNaN(value) && prefixExponent !== undefined ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); // Break the formatted value into the integer “value” part that can be // grouped, and fractional or exponential “suffix” part that is not. @@ -5446,12 +5460,11 @@ function formatLocale$1(locale) { } function formatPrefix(specifier, value) { - var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), - e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, + var e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, k = Math.pow(10, -e), - prefix = prefixes[8 + e / 3]; + f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier), {suffix: prefixes[8 + e / 3]}); return function(value) { - return f(k * value) + prefix; + return f(k * value); }; } @@ -5731,9 +5744,9 @@ function loggish(transform) { return scale; } -function log() { +function log$1() { const scale = loggish(transformer$2()).domain([1, 10]); - scale.copy = () => copy$1(scale, log()).base(scale.base()); + scale.copy = () => copy$1(scale, log$1()).base(scale.base()); initRange.apply(scale, arguments); return scale; } @@ -7262,14 +7275,14 @@ function clearNow() { clockNow = 0; } -function Timer() { +function Timer$1() { this._call = this._time = this._next = null; } -Timer.prototype = timer.prototype = { - constructor: Timer, +Timer$1.prototype = timer.prototype = { + constructor: Timer$1, restart: function(callback, delay, time) { if (typeof callback !== "function") throw new TypeError("callback is not a function"); time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); @@ -7292,7 +7305,7 @@ Timer.prototype = timer.prototype = { }; function timer(callback, delay, time) { - var t = new Timer; + var t = new Timer$1; t.restart(callback, delay, time); return t; } @@ -7354,7 +7367,7 @@ function sleep(time) { } function timeout(callback, delay, time) { - var t = new Timer; + var t = new Timer$1; delay = delay == null ? 0 : +delay; t.restart(elapsed => { t.stop(); @@ -8510,10 +8523,28 @@ function createGrayPalette() { return new ColorPalette(palette); } +/** @summary Set list of colors for specified color palette + * @desc One also can redefine existing palette + * Array should contain several colors in RGB format like `rgb(10,10,10)` or `#ff00ff` + * @private */ + +const customPalettes = {}; + +function setColorPalette(id, colors) { + if (!Number.isInteger(id) || (id < 0) || !colors?.length) + return false; + + customPalettes[id] = colors; + return true; +} + /** @summary Create color palette * @private */ function getColorPalette(id, grayscale) { id = id || settings.Palette; + if (customPalettes[id]) + return new ColorPalette(customPalettes[id], grayscale); + if ((id > 0) && (id < 10)) return createGrayPalette(); if (id < 51) @@ -9536,7 +9567,7 @@ class BasePainter { * @return {Promise} with d3 selection for d3_body * @private */ async function _loadJSDOM() { - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(handle => { + return import('jsdom').then(handle => { if (!internals.nodejs_window) { internals.nodejs_window = (new handle.JSDOM('hello')).window; internals.nodejs_document = internals.nodejs_window.document; // used with three.js @@ -9601,9 +9632,14 @@ async function svgToImage(svg, image_format, args) { return internals.makePDF ? internals.makePDF(svg, args) : null; // required with df104.py/df105.py example with RCanvas or any special symbols in TLatex - const doctype = ''; + const doctype = '', + is_rgba = image_format === 'rgba'; if (isNodeJs()) { + if (image_format === 'jpeg') { + console.log('JPEG image format not supported in node.js, use PNG'); + return null; + } svg = encodeURIComponent(doctype + svg); svg = svg.replace(/%([0-9A-F]{2})/g, (match, p1) => { const c = String.fromCharCode('0x' + p1); @@ -9612,7 +9648,32 @@ async function svgToImage(svg, image_format, args) { const img_src = 'data:image/svg+xml;base64,' + btoa_func(decodeURIComponent(svg)); - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(async handle => { + // Use the newer and stabler `resvg-js` backend for converting SVG to PNG + if (settings.UseResvgJs) { + return import('@resvg/resvg-js').then(({ Resvg }) => { + const rawSvg = decodeURIComponent(svg), // raw SVG XML + resvg = new Resvg(rawSvg), // Initialize Resvg and create the PNG buffer + renderData = resvg.render(), + pngBuffer = renderData.asPng(); + + // Return raw RGBA pixels if caller requested it + if (is_rgba) { + return { + width: renderData.width, + height: renderData.height, + data: renderData.pixels + }; + } + + if (args?.as_buffer) + return pngBuffer; + + return 'data:image/png;base64,' + pngBuffer.toString('base64'); + }); + } + + // Fallback to `node-canvas` + return import('canvas').then(async handle => { return handle.default.loadImage(img_src).then(img => { const canvas = handle.default.createCanvas(img.width, img.height); @@ -9621,7 +9682,7 @@ async function svgToImage(svg, image_format, args) { if (args?.as_buffer) return canvas.toBuffer('image/' + image_format); - return image_format ? canvas.toDataURL('image/' + image_format) : canvas; + return image_format && !is_rgba ? canvas.toDataURL('image/' + image_format) : canvas; }); }); } @@ -9643,7 +9704,7 @@ async function svgToImage(svg, image_format, args) { if (args?.as_buffer && image_format) canvas.toBlob(blob => blob.arrayBuffer().then(resolveFunc), 'image/' + image_format); else - resolveFunc(image_format ? canvas.toDataURL('image/' + image_format) : canvas); + resolveFunc(image_format && !is_rgba ? canvas.toDataURL('image/' + image_format) : canvas); }; image.onerror = function(arg) { URL.revokeObjectURL(img_src); @@ -9759,7 +9820,7 @@ async function loadFontFile(fname) { } let path = locations.shift() + fname; console.log('loading font', path); - const pr = isNodeJs() ? Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(fs => { + const pr = isNodeJs() ? import('fs').then(fs => { const prefix = 'file://' + (process?.platform === 'win32' ? '/' : ''); if (path.indexOf(prefix) === 0) path = path.slice(prefix.length); @@ -11124,7 +11185,7 @@ async function loadMathjax() { return _loadJSDOM().then(handle => { JSDOM = handle.JSDOM; - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }); + return import('mathjax'); }).then(mj0 => { // return Promise with mathjax loading mj0.init({ @@ -14301,9 +14362,8 @@ class ObjectPainter extends BasePainter { } /** @summary Configure user-defined tooltip handler - * @desc Hook for the users to get tooltip information when mouse cursor moves over frame area + * @desc Hook for the users to get tooltip information when mouse cursor moves over then object * Handler function will be called every time when new data is selected - * when mouse leave frame area, handler(null) will be called * @param {function} handler - function called when tooltip is produced * @param {number} [tmout = 100] - delay in ms before tooltip delivered */ configureUserTooltipHandler(handler, tmout = 100) { @@ -14591,7 +14651,7 @@ Object.assign(internals.jsroot, { ObjectPainter, cleanup, resize }); * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ -const REVISION = '180'; +const REVISION = '183'; /** * Represents mouse buttons and interaction types in context of controls. @@ -15455,6 +15515,38 @@ const RGB_ETC2_Format = 37492; */ const RGBA_ETC2_EAC_Format = 37496; +/** + * EAC R11 UNORM format. + * + * @type {number} + * @constant + */ +const R11_EAC_Format = 37488; // 0x9270 + +/** + * EAC R11 SNORM format. + * + * @type {number} + * @constant + */ +const SIGNED_R11_EAC_Format = 37489; // 0x9271 + +/** + * EAC RG11 UNORM format. + * + * @type {number} + * @constant + */ +const RG11_EAC_Format = 37490; // 0x9272 + +/** + * EAC RG11 SNORM format. + * + * @type {number} + * @constant + */ +const SIGNED_RG11_EAC_Format = 37491; // 0x9273 + /** * ASTC RGBA 4x4 format. * @@ -15624,21 +15716,13 @@ const RED_GREEN_RGTC2_Format = 36285; const SIGNED_RED_GREEN_RGTC2_Format = 36286; /** - * Basic depth packing. + * The depth value is inverted (1.0 - z) for visualization purposes. * * @type {number} * @constant */ const BasicDepthPacking = 3200; -/** - * A depth value is packed into 32 bit RGBA. - * - * @type {number} - * @constant - */ -const RGBADepthPacking = 3201; - /** * Normal information is relative to the underlying surface. * @@ -15863,7 +15947,7 @@ const WebGPUCoordinateSystem = 2001; /** * This modules allows to dispatch event objects on custom JavaScript objects. * - * Main repository: [eventdispatcher.js]{@link https://github.com/mrdoob/eventdispatcher.js/} + * Main repository: [eventdispatcher.js](https://github.com/mrdoob/eventdispatcher.js/) * * Code Example: * ```js @@ -15989,6 +16073,276 @@ class EventDispatcher { } +/** + * Checks if an array contains values that require Uint32 representation. + * + * This function determines whether the array contains any values >= 65535, + * which would require a Uint32Array rather than a Uint16Array for proper storage. + * The function iterates from the end of the array, assuming larger values are + * typically located at the end. + * + * @private + * @param {Array} array - The array to check. + * @return {boolean} True if the array contains values >= 65535, false otherwise. + */ +function arrayNeedsUint32( array ) { + + // assumes larger values usually on last + + for ( let i = array.length - 1; i >= 0; -- i ) { + + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + + } + + return false; + +} + +/** + * Creates an XHTML element with the specified tag name. + * + * This function uses the XHTML namespace to create DOM elements, + * ensuring proper element creation in XML-based contexts. + * + * @private + * @param {string} name - The tag name of the element to create (e.g., 'canvas', 'div'). + * @return {HTMLElement} The created XHTML element. + */ +function createElementNS( name ) { + + return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); + +} + +/** + * Creates a canvas element configured for block display. + * + * This is a convenience function that creates a canvas element with + * display style set to 'block', which is commonly used in three.js + * rendering contexts to avoid inline element spacing issues. + * + * @return {HTMLCanvasElement} A canvas element with display set to 'block'. + */ +function createCanvasElement() { + + const canvas = createElementNS( 'canvas' ); + canvas.style.display = 'block'; + return canvas; + +} + +/** + * Internal cache for tracking warning messages to prevent duplicate warnings. + * + * @private + * @type {Object} + */ +const _cache = {}; + +/** + * Logs an informational message with the 'THREE.' prefix. + * + * If a custom console function is set via setConsoleFunction(), it will be used + * instead of the native console.log. The first parameter is treated as the + * method name and is automatically prefixed with 'THREE.'. + * + * @param {...any} params - The message components. The first param is used as + * the method name and prefixed with 'THREE.'. + */ +function log( ...params ) { + + const message = 'THREE.' + params.shift(); + + { + + console.log( message, ...params ); + + } + +} + +/** + * Enhances log/warn/error messages related to TSL. + * + * @param {Array} params - The original message parameters. + * @returns {Array} The filtered and enhanced message parameters. + */ +function enhanceLogMessage( params ) { + + const message = params[ 0 ]; + + if ( typeof message === 'string' && message.startsWith( 'TSL:' ) ) { + + const stackTrace = params[ 1 ]; + + if ( stackTrace && stackTrace.isStackTrace ) { + + params[ 0 ] += ' ' + stackTrace.getLocation(); + + } else { + + params[ 1 ] = 'Stack trace not available. Enable "THREE.Node.captureStackTrace" to capture stack traces.'; + + } + + } + + return params; + +} + +/** + * Logs a warning message with the 'THREE.' prefix. + * + * If a custom console function is set via setConsoleFunction(), it will be used + * instead of the native console.warn. The first parameter is treated as the + * method name and is automatically prefixed with 'THREE.'. + * + * @param {...any} params - The message components. The first param is used as + * the method name and prefixed with 'THREE.'. + */ +function warn( ...params ) { + + params = enhanceLogMessage( params ); + + const message = 'THREE.' + params.shift(); + + { + + const stackTrace = params[ 0 ]; + + if ( stackTrace && stackTrace.isStackTrace ) { + + console.warn( stackTrace.getError( message ) ); + + } else { + + console.warn( message, ...params ); + + } + + } + +} + +/** + * Logs an error message with the 'THREE.' prefix. + * + * If a custom console function is set via setConsoleFunction(), it will be used + * instead of the native console.error. The first parameter is treated as the + * method name and is automatically prefixed with 'THREE.'. + * + * @param {...any} params - The message components. The first param is used as + * the method name and prefixed with 'THREE.'. + */ +function error( ...params ) { + + params = enhanceLogMessage( params ); + + const message = 'THREE.' + params.shift(); + + { + + const stackTrace = params[ 0 ]; + + if ( stackTrace && stackTrace.isStackTrace ) { + + console.error( stackTrace.getError( message ) ); + + } else { + + console.error( message, ...params ); + + } + + } + +} + +/** + * Logs a warning message only once, preventing duplicate warnings. + * + * This function maintains an internal cache of warning messages and will only + * output each unique warning message once. Useful for warnings that may be + * triggered repeatedly but should only be shown to the user once. + * + * @param {...any} params - The warning message components. + */ +function warnOnce( ...params ) { + + const message = params.join( ' ' ); + + if ( message in _cache ) return; + + _cache[ message ] = true; + + warn( ...params ); + +} + +/** + * Asynchronously probes for WebGL sync object completion. + * + * This function creates a promise that resolves when the WebGL sync object + * signals completion or rejects if the sync operation fails. It uses polling + * at the specified interval to check the sync status without blocking the + * main thread. This is useful for GPU-CPU synchronization in WebGL contexts. + * + * @private + * @param {WebGL2RenderingContext} gl - The WebGL rendering context. + * @param {WebGLSync} sync - The WebGL sync object to wait for. + * @param {number} interval - The polling interval in milliseconds. + * @return {Promise} A promise that resolves when the sync completes or rejects if it fails. + */ +function probeAsync( gl, sync, interval ) { + + return new Promise( function ( resolve, reject ) { + + function probe() { + + switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) { + + case gl.WAIT_FAILED: + reject(); + break; + + case gl.TIMEOUT_EXPIRED: + setTimeout( probe, interval ); + break; + + default: + resolve(); + + } + + } + + setTimeout( probe, interval ); + + } ); + +} + +/** + * Used to select the correct depth functions + * when reversed depth buffer is used. + * + * @private + * @type {Object} + */ +const ReversedDepthFuncs = { + [ NeverDepth ]: AlwaysDepth, + [ LessDepth ]: GreaterDepth, + [ EqualDepth ]: NotEqualDepth, + [ LessEqualDepth ]: GreaterEqualDepth, + + [ AlwaysDepth ]: NeverDepth, + [ GreaterDepth ]: LessDepth, + [ NotEqualDepth ]: EqualDepth, + [ GreaterEqualDepth ]: LessEqualDepth, +}; + const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ]; let _seed = 1234567; @@ -15998,7 +16352,7 @@ const DEG2RAD = Math.PI / 180; const RAD2DEG = 180 / Math.PI; /** - * Generate a [UUID]{@link https://en.wikipedia.org/wiki/Universally_unique_identifier} + * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) * (universally unique identifier). * * @return {string} The UUID. @@ -16053,7 +16407,7 @@ function euclideanModulo( n, m ) { /** * Performs a linear mapping from range `` to range `` - * for the given value. + * for the given value. `a2` must be greater than `a1`. * * @param {number} x - The value to be mapped. * @param {number} a1 - Minimum value for range A. @@ -16111,7 +16465,7 @@ function lerp( x, y, t ) { /** * Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta * time to maintain frame rate independent movement. For details, see - * [Frame rate independent damping using lerp]{@link http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/}. + * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/). * * @param {number} x - The current point. * @param {number} y - The target point. @@ -16146,11 +16500,11 @@ function pingpong( x, length = 1 ) { * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to * the `min` and `max`. * - * See [Smoothstep]{@link http://en.wikipedia.org/wiki/Smoothstep} for more details. + * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details. * - * @param {number} x - The value to evaluate based on its position between min and max. - * @param {number} min - The min value. Any x value below min will be `0`. - * @param {number} max - The max value. Any x value above max will be `1`. + * @param {number} x - The value to evaluate based on its position between `min` and `max`. + * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`. + * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`. * @return {number} The alternated value. */ function smoothstep( x, min, max ) { @@ -16165,12 +16519,12 @@ function smoothstep( x, min, max ) { } /** - * A [variation on smoothstep]{@link https://en.wikipedia.org/wiki/Smoothstep#Variations} - * that has zero 1st and 2nd order derivatives at x=0 and x=1. + * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations) + * that has zero 1st and 2nd order derivatives at `x=0` and `x=1`. * - * @param {number} x - The value to evaluate based on its position between min and max. - * @param {number} min - The min value. Any x value below min will be `0`. - * @param {number} max - The max value. Any x value above max will be `1`. + * @param {number} x - The value to evaluate based on its position between `min` and `max`. + * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`. + * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`. * @return {number} The alternated value. */ function smootherstep( x, min, max ) { @@ -16283,7 +16637,7 @@ function isPowerOfTwo( value ) { /** * Returns the smallest power of two that is greater than or equal to the given number. * - * @param {number} value - The value to find a POT for. + * @param {number} value - The value to find a POT for. Must be greater than `0`. * @return {number} The smallest power of two that is greater than or equal to the given number. */ function ceilPowerOfTwo( value ) { @@ -16295,7 +16649,7 @@ function ceilPowerOfTwo( value ) { /** * Returns the largest power of two that is less than or equal to the given number. * - * @param {number} value - The value to find a POT for. + * @param {number} value - The value to find a POT for. Must be greater than `0`. * @return {number} The largest power of two that is less than or equal to the given number. */ function floorPowerOfTwo( value ) { @@ -16305,7 +16659,7 @@ function floorPowerOfTwo( value ) { } /** - * Sets the given quaternion from the [Intrinsic Proper Euler Angles]{@link https://en.wikipedia.org/wiki/Euler_angles} + * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles) * defined by the given angles and order. * * Rotations are applied to the axes in the order specified by order: @@ -16361,7 +16715,7 @@ function setQuaternionFromProperEuler( q, a, b, c, order ) { break; default: - console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); + warn( 'MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); } @@ -16470,7 +16824,7 @@ const MathUtils = { DEG2RAD: DEG2RAD, RAD2DEG: RAD2DEG, /** - * Generate a [UUID]{@link https://en.wikipedia.org/wiki/Universally_unique_identifier} + * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) * (universally unique identifier). * * @static @@ -16541,7 +16895,7 @@ const MathUtils = { /** * Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta * time to maintain frame rate independent movement. For details, see - * [Frame rate independent damping using lerp]{@link http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/}. + * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/). * * @static * @method @@ -16568,7 +16922,7 @@ const MathUtils = { * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to * the `min` and `max`. * - * See [Smoothstep]{@link http://en.wikipedia.org/wiki/Smoothstep} for more details. + * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details. * * @static * @method @@ -16579,7 +16933,7 @@ const MathUtils = { */ smoothstep: smoothstep, /** - * A [variation on smoothstep]{@link https://en.wikipedia.org/wiki/Smoothstep#Variations} + * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations) * that has zero 1st and 2nd order derivatives at x=0 and x=1. * * @static @@ -16674,7 +17028,7 @@ const MathUtils = { */ floorPowerOfTwo: floorPowerOfTwo, /** - * Sets the given quaternion from the [Intrinsic Proper Euler Angles]{@link https://en.wikipedia.org/wiki/Euler_angles} + * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles) * defined by the given angles and order. * * Rotations are applied to the axes in the order specified by order: @@ -17648,7 +18002,7 @@ class Quaternion { /** * Interpolates between two quaternions via SLERP. This implementation assumes the - * quaternion data are managed in flat arrays. + * quaternion data are managed in flat arrays. * * @param {Array} dst - The destination array. * @param {number} dstOffset - An offset into the destination array. @@ -17656,70 +18010,61 @@ class Quaternion { * @param {number} srcOffset0 - An offset into the first source array. * @param {Array} src1 - The source array of the second quaternion. * @param {number} srcOffset1 - An offset into the second source array. - * @param {number} t - The interpolation factor in the range `[0,1]`. + * @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate. * @see {@link Quaternion#slerp} */ static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - // fuzz-free, array-based Quaternion SLERP operation - let x0 = src0[ srcOffset0 + 0 ], y0 = src0[ srcOffset0 + 1 ], z0 = src0[ srcOffset0 + 2 ], w0 = src0[ srcOffset0 + 3 ]; - const x1 = src1[ srcOffset1 + 0 ], + let x1 = src1[ srcOffset1 + 0 ], y1 = src1[ srcOffset1 + 1 ], z1 = src1[ srcOffset1 + 2 ], w1 = src1[ srcOffset1 + 3 ]; - if ( t === 0 ) { - - dst[ dstOffset + 0 ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - return; + if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - } + let dot = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1; - if ( t === 1 ) { + if ( dot < 0 ) { - dst[ dstOffset + 0 ] = x1; - dst[ dstOffset + 1 ] = y1; - dst[ dstOffset + 2 ] = z1; - dst[ dstOffset + 3 ] = w1; - return; + x1 = - x1; + y1 = - y1; + z1 = - z1; + w1 = - w1; - } + dot = - dot; - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + } let s = 1 - t; - const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, - dir = ( cos >= 0 ? 1 : -1 ), - sqrSin = 1 - cos * cos; - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { + if ( dot < 0.9995 ) { - const sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + // slerp - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + const theta = Math.acos( dot ); + const sin = Math.sin( theta ); - } + s = Math.sin( s * theta ) / sin; + t = Math.sin( t * theta ) / sin; - const tDir = t * dir; + x0 = x0 * s + x1 * t; + y0 = y0 * s + y1 * t; + z0 = z0 * s + z1 * t; + w0 = w0 * s + w1 * t; - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + } else { + + // for small angles, lerp then normalize - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + x0 = x0 * s + x1 * t; + y0 = y0 * s + y1 * t; + z0 = z0 * s + z1 * t; + w0 = w0 * s + w1 * t; const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); @@ -17973,7 +18318,7 @@ class Quaternion { break; default: - console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); + warn( 'Quaternion: .setFromEuler() encountered an unknown order: ' + order ); } @@ -18321,77 +18666,61 @@ class Quaternion { } /** - * Performs a spherical linear interpolation between quaternions. + * Performs a spherical linear interpolation between this quaternion and the target quaternion. * * @param {Quaternion} qb - The target quaternion. - * @param {number} t - The interpolation factor in the closed interval `[0, 1]`. + * @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate. * @return {Quaternion} A reference to this quaternion. */ slerp( qb, t ) { - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - const x = this._x, y = this._y, z = this._z, w = this._w; + let x = qb._x, y = qb._y, z = qb._z, w = qb._w; - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + let dot = this.dot( qb ); - let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; + if ( dot < 0 ) { - if ( cosHalfTheta < 0 ) { + x = - x; + y = - y; + z = - z; + w = - w; - this._w = - qb._w; - this._x = - qb._x; - this._y = - qb._y; - this._z = - qb._z; + dot = - dot; - cosHalfTheta = - cosHalfTheta; + } - } else { + let s = 1 - t; - this.copy( qb ); + if ( dot < 0.9995 ) { - } + // slerp - if ( cosHalfTheta >= 1.0 ) { + const theta = Math.acos( dot ); + const sin = Math.sin( theta ); - this._w = w; - this._x = x; - this._y = y; - this._z = z; + s = Math.sin( s * theta ) / sin; + t = Math.sin( t * theta ) / sin; - return this; + this._x = this._x * s + x * t; + this._y = this._y * s + y * t; + this._z = this._z * s + z * t; + this._w = this._w * s + w * t; - } + this._onChangeCallback(); - const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; + } else { - if ( sqrSinHalfTheta <= Number.EPSILON ) { + // for small angles, lerp then normalize - const s = 1 - t; - this._w = s * w + t * this._w; - this._x = s * x + t * this._x; - this._y = s * y + t * this._y; - this._z = s * z + t * this._z; + this._x = this._x * s + x * t; + this._y = this._y * s + y * t; + this._z = this._z * s + z * t; + this._w = this._w * s + w * t; this.normalize(); // normalize calls _onChangeCallback() - return this; - } - const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); - const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); - - this._onChangeCallback(); - return this; } @@ -18647,7 +18976,7 @@ class Vector3 { } /** - * Sets the vector's x component to the given value + * Sets the vector's x component to the given value. * * @param {number} x - The value to set. * @return {Vector3} A reference to this vector. @@ -18661,7 +18990,7 @@ class Vector3 { } /** - * Sets the vector's y component to the given value + * Sets the vector's y component to the given value. * * @param {number} y - The value to set. * @return {Vector3} A reference to this vector. @@ -18675,7 +19004,7 @@ class Vector3 { } /** - * Sets the vector's z component to the given value + * Sets the vector's z component to the given value. * * @param {number} z - The value to set. * @return {Vector3} A reference to this vector. @@ -18928,7 +19257,7 @@ class Vector3 { */ applyEuler( euler ) { - return this.applyQuaternion( _quaternion$2.setFromEuler( euler ) ); + return this.applyQuaternion( _quaternion$3.setFromEuler( euler ) ); } @@ -18941,7 +19270,7 @@ class Vector3 { */ applyAxisAngle( axis, angle ) { - return this.applyQuaternion( _quaternion$2.setFromAxisAngle( axis, angle ) ); + return this.applyQuaternion( _quaternion$3.setFromAxisAngle( axis, angle ) ); } @@ -19285,8 +19614,6 @@ class Vector3 { } - // TODO lengthSquared? - /** * Computes the square of the Euclidean length (straight-line length) from * (0, 0, 0) to (x, y, z). If you are comparing the lengths of vectors, you should @@ -19797,7 +20124,7 @@ class Vector3 { } const _vector$8 = /*@__PURE__*/ new Vector3(); -const _quaternion$2 = /*@__PURE__*/ new Quaternion(); +const _quaternion$3 = /*@__PURE__*/ new Quaternion(); /** * Represents a 3x3 matrix. @@ -19805,7 +20132,7 @@ const _quaternion$2 = /*@__PURE__*/ new Quaternion(); * A Note on Row-Major and Column-Major Ordering: * * The constructor and {@link Matrix3#set} method take arguments in - * [row-major]{@link https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order} + * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order) * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order. * This means that calling: * ```js @@ -20079,7 +20406,7 @@ class Matrix3 { } /** - * Inverts this matrix, using the [analytic method]{@link https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution}. + * Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution). * You can not invert with a determinant of zero. If you attempt this, the method produces * a zero matrix instead. * @@ -20411,75 +20738,6 @@ class Matrix3 { const _m3 = /*@__PURE__*/ new Matrix3(); -function arrayNeedsUint32( array ) { - - // assumes larger values usually on last - - for ( let i = array.length - 1; i >= 0; -- i ) { - - if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 - - } - - return false; - -} - -function createElementNS( name ) { - - return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); - -} - -function createCanvasElement() { - - const canvas = createElementNS( 'canvas' ); - canvas.style.display = 'block'; - return canvas; - -} - -const _cache = {}; - -function warnOnce( message ) { - - if ( message in _cache ) return; - - _cache[ message ] = true; - - console.warn( message ); - -} - -function probeAsync( gl, sync, interval ) { - - return new Promise( function ( resolve, reject ) { - - function probe() { - - switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) { - - case gl.WAIT_FAILED: - reject(); - break; - - case gl.TIMEOUT_EXPIRED: - setTimeout( probe, interval ); - break; - - default: - resolve(); - - } - - } - - setTimeout( probe, interval ); - - } ); - -} - const LINEAR_REC709_TO_XYZ = /*@__PURE__*/ new Matrix3().set( 0.4123908, 0.3575843, 0.1804808, 0.2126390, 0.7151687, 0.0721923, @@ -20625,7 +20883,7 @@ function createColorManagement() { fromWorkingColorSpace: function ( color, targetColorSpace ) { - warnOnce( 'THREE.ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().' ); // @deprecated, r177 + warnOnce( 'ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().' ); // @deprecated, r177 return ColorManagement.workingToColorSpace( color, targetColorSpace ); @@ -20633,7 +20891,7 @@ function createColorManagement() { toWorkingColorSpace: function ( color, sourceColorSpace ) { - warnOnce( 'THREE.ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().' ); // @deprecated, r177 + warnOnce( 'ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().' ); // @deprecated, r177 return ColorManagement.colorSpaceToWorking( color, sourceColorSpace ); @@ -20816,7 +21074,7 @@ class ImageUtils { } else { - console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + warn( 'ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); return image; } @@ -20911,7 +21169,7 @@ class Source { target.set( data.videoWidth, data.videoHeight, 0 ); - } else if ( data instanceof VideoFrame ) { + } else if ( ( typeof VideoFrame !== 'undefined' ) && ( data instanceof VideoFrame ) ) { target.set( data.displayHeight, data.displayWidth, 0 ); @@ -21041,7 +21299,7 @@ function serializeImage( image ) { } else { - console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + warn( 'Texture: Unable to serialize Texture.' ); return {}; } @@ -21101,7 +21359,7 @@ class Texture extends EventDispatcher { Object.defineProperty( this, 'id', { value: _textureId ++ } ); /** - * The UUID of the material. + * The UUID of the texture. * * @type {string} * @readonly @@ -21109,7 +21367,7 @@ class Texture extends EventDispatcher { this.uuid = generateUUID(); /** - * The name of the material. + * The name of the texture. * * @type {string} */ @@ -21191,7 +21449,7 @@ class Texture extends EventDispatcher { * texture samples being used. * * @type {number} - * @default 0 + * @default Texture.DEFAULT_ANISOTROPY */ this.anisotropy = anisotropy; @@ -21555,7 +21813,7 @@ class Texture extends EventDispatcher { if ( newValue === undefined ) { - console.warn( `THREE.Texture.setValues(): parameter '${ key }' has value of undefined.` ); + warn( `Texture.setValues(): parameter '${ key }' has value of undefined.` ); continue; } @@ -21564,7 +21822,7 @@ class Texture extends EventDispatcher { if ( currentValue === undefined ) { - console.warn( `THREE.Texture.setValues(): property '${ key }' does not exist.` ); + warn( `Texture.setValues(): property '${ key }' does not exist.` ); continue; } @@ -23011,10 +23269,6 @@ class RenderTarget extends EventDispatcher { */ this.viewport = new Vector4( 0, 0, width, height ); - const image = { width: width, height: height, depth: options.depth }; - - const texture = new Texture( image ); - /** * An array of textures. Each color attachment is represented as a separate texture. * Has at least a single entry for the default color attachment. @@ -23023,6 +23277,9 @@ class RenderTarget extends EventDispatcher { */ this.textures = []; + const image = { width: width, height: height, depth: options.depth }; + const texture = new Texture( image ); + const count = options.count; for ( let i = 0; i < count; i ++ ) { @@ -23181,7 +23438,16 @@ class RenderTarget extends EventDispatcher { this.textures[ i ].image.width = width; this.textures[ i ].image.height = height; this.textures[ i ].image.depth = depth; - this.textures[ i ].isArrayTexture = this.textures[ i ].image.depth > 1; + + if ( this.textures[ i ].isData3DTexture !== true ) { // Fix for #31693 + + // TODO: Reconsider setting isArrayTexture flag here and in the ctor of Texture. + // Maybe a method `isArrayTexture()` or just a getter could replace a flag since + // both are evaluated on each call? + + this.textures[ i ].isArrayTexture = this.textures[ i ].image.depth > 1; + + } } @@ -23571,7 +23837,7 @@ class Color { /** * Sets this color from a CSS-style string. For example, `rgb(250, 0,0)`, * `rgb(100%, 0%, 0%)`, `hsl(0, 100%, 50%)`, `#ff0000`, `#f00`, or `red` ( or - * any [X11 color name]{@link https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart} - + * any [X11 color name](https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart) - * all 140 color names are supported). * * @param {string} style - Color as a CSS-style string. @@ -23586,7 +23852,7 @@ class Color { if ( parseFloat( string ) < 1 ) { - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + warn( 'Color: Alpha component of ' + style + ' will be ignored.' ); } @@ -23662,7 +23928,7 @@ class Color { default: - console.warn( 'THREE.Color: Unknown color model ' + style ); + warn( 'Color: Unknown color model ' + style ); } @@ -23690,7 +23956,7 @@ class Color { } else { - console.warn( 'THREE.Color: Invalid hex color ' + style ); + warn( 'Color: Invalid hex color ' + style ); } @@ -23730,7 +23996,7 @@ class Color { } else { // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + warn( 'Color: Unknown color ' + style ); } @@ -25465,7 +25731,7 @@ class Sphere { * Returns a serialized structure of the bounding sphere. * * @param {Object} json - The serialized json to set the sphere from. - * @return {Box3} A reference to this bounding sphere. + * @return {Sphere} A reference to this bounding sphere. */ fromJSON( json ) { @@ -25483,7 +25749,7 @@ const _normalMatrix = /*@__PURE__*/ new Matrix3(); /** * A two dimensional surface that extends infinitely in 3D space, represented - * in [Hessian normal form]{@link http://mathworld.wolfram.com/HessianNormalForm.html} + * in [Hessian normal form](http://mathworld.wolfram.com/HessianNormalForm.html) * by a unit length normal vector and a constant. */ class Plane { @@ -26121,7 +26387,7 @@ class Frustum { * Represents a 4x4 matrix. * * The most common use of a 4x4 matrix in 3D computer graphics is as a transformation matrix. - * For an introduction to transformation matrices as used in WebGL, check out [this tutorial]{@link https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices} + * For an introduction to transformation matrices as used in WebGL, check out [this tutorial](https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices) * * This allows a 3D vector representing a point in 3D space to undergo * transformations such as translation, rotation, shear, scale, reflection, @@ -26131,7 +26397,7 @@ class Frustum { * A Note on Row-Major and Column-Major Ordering: * * The constructor and {@link Matrix3#set} method take arguments in - * [row-major]{@link https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order} + * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order) * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order. * This means that calling: * ```js @@ -26350,6 +26616,16 @@ class Matrix4 { */ extractBasis( xAxis, yAxis, zAxis ) { + if ( this.determinant() === 0 ) { + + xAxis.set( 1, 0, 0 ); + yAxis.set( 0, 1, 0 ); + zAxis.set( 0, 0, 1 ); + + return this; + + } + xAxis.setFromMatrixColumn( this, 0 ); yAxis.setFromMatrixColumn( this, 1 ); zAxis.setFromMatrixColumn( this, 2 ); @@ -26390,6 +26666,12 @@ class Matrix4 { */ extractRotation( m ) { + if ( m.determinant() === 0 ) { + + return this.identity(); + + } + const te = this.elements; const me = m.elements; @@ -26425,7 +26707,7 @@ class Matrix4 { * Sets the rotation component (the upper left 3x3 matrix) of this matrix to * the rotation specified by the given Euler angles. The rest of * the matrix is set to the identity. Depending on the {@link Euler#order}, - * there are six possible outcomes. See [this page]{@link https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix} + * there are six possible outcomes. See [this page](https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix) * for a complete list. * * @param {Euler} euler - The Euler angles. @@ -26555,7 +26837,7 @@ class Matrix4 { /** * Sets the rotation component of this matrix to the rotation specified by - * the given Quaternion as outlined [here]{@link https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion} + * the given Quaternion as outlined [here](https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion) * The rest of the matrix is set to the identity. * * @param {Quaternion} q - The Quaternion. @@ -26717,7 +26999,7 @@ class Matrix4 { /** * Computes and returns the determinant of this matrix. * - * Based on the method outlined [here]{@link http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.html}. + * Based on the method outlined [here](http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.html). * * @return {number} The determinant. */ @@ -26730,43 +27012,18 @@ class Matrix4 { const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; - //TODO: make this more efficient - - return ( - n41 * ( - + n14 * n23 * n32 - - n13 * n24 * n32 - - n14 * n22 * n33 - + n12 * n24 * n33 - + n13 * n22 * n34 - - n12 * n23 * n34 - ) + - n42 * ( - + n11 * n23 * n34 - - n11 * n24 * n33 - + n14 * n21 * n33 - - n13 * n21 * n34 - + n13 * n24 * n31 - - n14 * n23 * n31 - ) + - n43 * ( - + n11 * n24 * n32 - - n11 * n22 * n34 - - n14 * n21 * n32 - + n12 * n21 * n34 - + n14 * n22 * n31 - - n12 * n24 * n31 - ) + - n44 * ( - - n13 * n22 * n31 - - n11 * n23 * n32 - + n11 * n22 * n33 - + n13 * n21 * n32 - - n12 * n21 * n33 - + n12 * n23 * n31 - ) + const t11 = n23 * n34 - n24 * n33; + const t12 = n22 * n34 - n24 * n32; + const t13 = n22 * n33 - n23 * n32; - ); + const t21 = n21 * n34 - n24 * n31; + const t22 = n21 * n33 - n23 * n31; + const t23 = n21 * n32 - n22 * n31; + + return n11 * ( n42 * t11 - n43 * t12 + n44 * t13 ) - + n12 * ( n41 * t11 - n43 * t21 + n44 * t22 ) + + n13 * ( n41 * t12 - n42 * t21 + n44 * t23 ) - + n14 * ( n41 * t13 - n42 * t22 + n43 * t23 ); } @@ -26824,7 +27081,7 @@ class Matrix4 { } /** - * Inverts this matrix, using the [analytic method]{@link https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution}. + * Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution). * You can not invert with a determinant of zero. If you attempt this, the method produces * a zero matrix instead. * @@ -26832,7 +27089,7 @@ class Matrix4 { */ invert() { - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + // based on https://github.com/toji/gl-matrix const te = this.elements, n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ], @@ -26840,36 +27097,44 @@ class Matrix4 { n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ], n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ], - t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, - t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, - t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, - t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; - - const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + t1 = n11 * n22 - n21 * n12, + t2 = n11 * n32 - n31 * n12, + t3 = n11 * n42 - n41 * n12, + t4 = n21 * n32 - n31 * n22, + t5 = n21 * n42 - n41 * n22, + t6 = n31 * n42 - n41 * n32, + t7 = n13 * n24 - n23 * n14, + t8 = n13 * n34 - n33 * n14, + t9 = n13 * n44 - n43 * n14, + t10 = n23 * n34 - n33 * n24, + t11 = n23 * n44 - n43 * n24, + t12 = n33 * n44 - n43 * n34; + + const det = t1 * t12 - t2 * t11 + t3 * t10 + t4 * t9 - t5 * t8 + t6 * t7; if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); const detInv = 1 / det; - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; - te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; - te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; + te[ 0 ] = ( n22 * t12 - n32 * t11 + n42 * t10 ) * detInv; + te[ 1 ] = ( n31 * t11 - n21 * t12 - n41 * t10 ) * detInv; + te[ 2 ] = ( n24 * t6 - n34 * t5 + n44 * t4 ) * detInv; + te[ 3 ] = ( n33 * t5 - n23 * t6 - n43 * t4 ) * detInv; - te[ 4 ] = t12 * detInv; - te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; - te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; - te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; + te[ 4 ] = ( n32 * t9 - n12 * t12 - n42 * t8 ) * detInv; + te[ 5 ] = ( n11 * t12 - n31 * t9 + n41 * t8 ) * detInv; + te[ 6 ] = ( n34 * t3 - n14 * t6 - n44 * t2 ) * detInv; + te[ 7 ] = ( n13 * t6 - n33 * t3 + n43 * t2 ) * detInv; - te[ 8 ] = t13 * detInv; - te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; - te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; - te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; + te[ 8 ] = ( n12 * t11 - n22 * t9 + n42 * t7 ) * detInv; + te[ 9 ] = ( n21 * t9 - n11 * t11 - n41 * t7 ) * detInv; + te[ 10 ] = ( n14 * t5 - n24 * t3 + n44 * t1 ) * detInv; + te[ 11 ] = ( n23 * t3 - n13 * t5 - n43 * t1 ) * detInv; - te[ 12 ] = t14 * detInv; - te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; - te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; - te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; + te[ 12 ] = ( n22 * t8 - n12 * t10 - n32 * t7 ) * detInv; + te[ 13 ] = ( n11 * t10 - n21 * t8 + n31 * t7 ) * detInv; + te[ 14 ] = ( n24 * t2 - n14 * t4 - n34 * t1 ) * detInv; + te[ 15 ] = ( n13 * t4 - n23 * t2 + n33 * t1 ) * detInv; return this; @@ -27027,7 +27292,7 @@ class Matrix4 { * the given angle. * * This is a somewhat controversial but mathematically sound alternative to - * rotating via Quaternions. See the discussion [here]{@link https://www.gamedev.net/articles/programming/math-and-physics/do-we-really-need-quaternions-r1199}. + * rotating via Quaternions. See the discussion [here](https://www.gamedev.net/articles/programming/math-and-physics/do-we-really-need-quaternions-r1199). * * @param {Vector3} axis - The normalized rotation axis. * @param {number} angle - The rotation in radians. @@ -27167,18 +27432,28 @@ class Matrix4 { const te = this.elements; + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; + + const det = this.determinant(); + + if ( det === 0 ) { + + scale.set( 1, 1, 1 ); + quaternion.identity(); + + return this; + + } + let sx = _v1$4.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); const sy = _v1$4.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); const sz = _v1$4.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); - // if determine is negative, we need to invert one scale - const det = this.determinant(); + // if determinant is negative, we need to invert one scale if ( det < 0 ) sx = - sx; - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; - // scale the rotation part _m1$4.copy( this ); @@ -28443,7 +28718,7 @@ class Float32BufferAttribute extends BufferAttribute { } const _matrix$2 = /*@__PURE__*/ new Matrix4(); -const _quaternion$1 = /*@__PURE__*/ new Quaternion(); +const _quaternion$2 = /*@__PURE__*/ new Quaternion(); /** * A class representing Euler angles. @@ -28744,7 +29019,7 @@ class Euler { default: - console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); + warn( 'Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); } @@ -28797,9 +29072,9 @@ class Euler { */ reorder( newOrder ) { - _quaternion$1.setFromEuler( this ); + _quaternion$2.setFromEuler( this ); - return this.setFromQuaternion( _quaternion$1, newOrder ); + return this.setFromQuaternion( _quaternion$2, newOrder ); } @@ -29011,9 +29286,9 @@ const _q1 = /*@__PURE__*/ new Quaternion(); const _m1$3 = /*@__PURE__*/ new Matrix4(); const _target = /*@__PURE__*/ new Vector3(); -const _position$1 = /*@__PURE__*/ new Vector3(); -const _scale = /*@__PURE__*/ new Vector3(); -const _quaternion = /*@__PURE__*/ new Quaternion(); +const _position$2 = /*@__PURE__*/ new Vector3(); +const _scale$1 = /*@__PURE__*/ new Vector3(); +const _quaternion$1 = /*@__PURE__*/ new Quaternion(); const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); @@ -29238,7 +29513,8 @@ class Object3D extends EventDispatcher { /** * When set to `true`, the engine automatically computes the local matrix from position, - * rotation and scale every frame. + * rotation and scale every frame. If set to `false`, the app is responsible for recomputing + * the local matrix by calling `updateMatrix()`. * * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_AUTO_UPDATE`. * @@ -29249,7 +29525,8 @@ class Object3D extends EventDispatcher { /** * When set to `true`, the engine automatically computes the world matrix from the current local - * matrix and the object's transformation hierarchy. + * matrix and the object's transformation hierarchy. If set to `false`, the app is responsible for + * recomputing the world matrix by directly updating the `matrixWorld` property. * * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE`. * @@ -29350,6 +29627,19 @@ class Object3D extends EventDispatcher { */ this.customDistanceMaterial = undefined; + /** + * Whether the 3D object is supposed to be static or not. If set to `true`, it means + * the 3D object is not going to be changed after the initial renderer. This includes + * geometry and material settings. A static 3D object can be processed by the renderer + * slightly faster since certain state checks can be bypassed. + * + * Only relevant in context of {@link WebGPURenderer}. + * + * @type {boolean} + * @default false + */ + this.static = false; + /** * An object that can be used to store custom data about the 3D object. It * should not hold references to functions as these will not be cloned. @@ -29358,6 +29648,16 @@ class Object3D extends EventDispatcher { */ this.userData = {}; + /** + * The pivot point for rotation and scale transformations. + * When set, rotation and scale are applied around this point + * instead of the object's origin. + * + * @type {?Vector3} + * @default null + */ + this.pivot = null; + } /** @@ -29640,7 +29940,7 @@ class Object3D extends EventDispatcher { } /** - * Converts the given vector from this 3D object's word space to local space. + * Converts the given vector from this 3D object's world space to local space. * * @param {Vector3} vector - The vector to convert. * @return {Vector3} The converted vector. @@ -29680,15 +29980,15 @@ class Object3D extends EventDispatcher { this.updateWorldMatrix( true, false ); - _position$1.setFromMatrixPosition( this.matrixWorld ); + _position$2.setFromMatrixPosition( this.matrixWorld ); if ( this.isCamera || this.isLight ) { - _m1$3.lookAt( _position$1, _target, this.up ); + _m1$3.lookAt( _position$2, _target, this.up ); } else { - _m1$3.lookAt( _target, _position$1, this.up ); + _m1$3.lookAt( _target, _position$2, this.up ); } @@ -29730,7 +30030,7 @@ class Object3D extends EventDispatcher { if ( object === this ) { - console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); + error( 'Object3D.add: object can\'t be added as a child of itself.', object ); return this; } @@ -29749,7 +30049,7 @@ class Object3D extends EventDispatcher { } else { - console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); + error( 'Object3D.add: object not an instance of THREE.Object3D.', object ); } @@ -29982,7 +30282,7 @@ class Object3D extends EventDispatcher { this.updateWorldMatrix( true, false ); - this.matrixWorld.decompose( _position$1, target, _scale ); + this.matrixWorld.decompose( _position$2, target, _scale$1 ); return target; @@ -29998,7 +30298,7 @@ class Object3D extends EventDispatcher { this.updateWorldMatrix( true, false ); - this.matrixWorld.decompose( _position$1, _quaternion, target ); + this.matrixWorld.decompose( _position$2, _quaternion$1, target ); return target; @@ -30105,6 +30405,19 @@ class Object3D extends EventDispatcher { this.matrix.compose( this.position, this.quaternion, this.scale ); + const pivot = this.pivot; + + if ( pivot !== null ) { + + const px = pivot.x, py = pivot.y, pz = pivot.z; + const te = this.matrix.elements; + + te[ 12 ] += px - te[ 0 ] * px - te[ 4 ] * py - te[ 8 ] * pz; + te[ 13 ] += py - te[ 1 ] * px - te[ 5 ] * py - te[ 9 ] * pz; + te[ 14 ] += pz - te[ 2 ] * px - te[ 6 ] * py - te[ 10 ] * pz; + + } + this.matrixWorldNeedsUpdate = true; } @@ -30118,7 +30431,7 @@ class Object3D extends EventDispatcher { * `true` by default. Set these flags to `false` if you need more control over the update matrix process. * * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even - * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`. + * when {@link Object3D#matrixWorldNeedsUpdate} is `false`. */ updateMatrixWorld( force ) { @@ -30263,14 +30576,20 @@ class Object3D extends EventDispatcher { if ( this.visible === false ) object.visible = false; if ( this.frustumCulled === false ) object.frustumCulled = false; if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; + if ( this.static !== false ) object.static = this.static; if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; object.layers = this.layers.mask; object.matrix = this.matrix.toArray(); object.up = this.up.toArray(); + if ( this.pivot !== null ) object.pivot = this.pivot.toArray(); + if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; + if ( this.morphTargetDictionary !== undefined ) object.morphTargetDictionary = Object.assign( {}, this.morphTargetDictionary ); + if ( this.morphTargetInfluences !== undefined ) object.morphTargetInfluences = this.morphTargetInfluences.slice(); + // object specific properties if ( this.isInstancedMesh ) { @@ -30544,6 +30863,12 @@ class Object3D extends EventDispatcher { this.quaternion.copy( source.quaternion ); this.scale.copy( source.scale ); + if ( source.pivot !== null ) { + + this.pivot = source.pivot.clone(); + + } + this.matrix.copy( source.matrix ); this.matrixWorld.copy( source.matrixWorld ); @@ -30561,6 +30886,8 @@ class Object3D extends EventDispatcher { this.frustumCulled = source.frustumCulled; this.renderOrder = source.renderOrder; + this.static = source.static; + this.animations = source.animations.slice(); this.userData = JSON.parse( JSON.stringify( source.userData ) ); @@ -30713,6 +31040,16 @@ class BufferGeometry extends EventDispatcher { */ this.indirect = null; + /** + * The offset, in bytes, into the indirect drawing buffer where the value data begins. If an array is provided, multiple indirect draw calls will be made for each offset. + * + * Can only be used with {@link WebGPURenderer} and a WebGPU backend. + * + * @type {number|Array} + * @default 0 + */ + this.indirectOffset = 0; + /** * This dictionary has as id the name of the attribute to be set and as value * the buffer attribute to set it to. Rather than accessing this property directly, @@ -30726,7 +31063,7 @@ class BufferGeometry extends EventDispatcher { * This dictionary holds the morph targets of the geometry. * * Note: Once the geometry has been rendered, the morph attribute data cannot - * be changed. You will have to call `dispose()?, and create a new geometry instance. + * be changed. You will have to call `dispose()`, and create a new geometry instance. * * @type {Object} */ @@ -30826,11 +31163,13 @@ class BufferGeometry extends EventDispatcher { * Sets the given indirect attribute to this geometry. * * @param {BufferAttribute} indirect - The attribute holding indirect draw calls. + * @param {number|Array} [indirectOffset=0] - The offset, in bytes, into the indirect drawing buffer where the value data begins. If an array is provided, multiple indirect draw calls will be made for each offset. * @return {BufferGeometry} A reference to this instance. */ - setIndirect( indirect ) { + setIndirect( indirect, indirectOffset = 0 ) { this.indirect = indirect; + this.indirectOffset = indirectOffset; return this; @@ -31198,7 +31537,7 @@ class BufferGeometry extends EventDispatcher { if ( points.length > positionAttribute.count ) { - console.warn( 'THREE.BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry.' ); + warn( 'BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry.' ); } @@ -31228,7 +31567,7 @@ class BufferGeometry extends EventDispatcher { if ( position && position.isGLBufferAttribute ) { - console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); + error( 'BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); this.boundingBox.set( new Vector3( - Infinity, - Infinity, - Infinity ), @@ -31279,7 +31618,7 @@ class BufferGeometry extends EventDispatcher { if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); + error( 'BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); } @@ -31303,7 +31642,7 @@ class BufferGeometry extends EventDispatcher { if ( position && position.isGLBufferAttribute ) { - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); + error( 'BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); this.boundingSphere.set( new Vector3(), Infinity ); @@ -31394,7 +31733,7 @@ class BufferGeometry extends EventDispatcher { if ( isNaN( this.boundingSphere.radius ) ) { - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); + error( 'BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); } @@ -31422,7 +31761,7 @@ class BufferGeometry extends EventDispatcher { attributes.normal === undefined || attributes.uv === undefined ) { - console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); + error( 'BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); return; } @@ -31732,7 +32071,7 @@ class BufferGeometry extends EventDispatcher { if ( this.index === null ) { - console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); + warn( 'BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); return this; } @@ -32058,6 +32397,7 @@ class BufferGeometry extends EventDispatcher { * ``` * * @augments BufferGeometry + * @demo scenes/geometry-browser.html#BoxGeometry */ class BoxGeometry extends BufferGeometry { @@ -32269,6 +32609,7 @@ class BoxGeometry extends BufferGeometry { * ``` * * @augments BufferGeometry + * @demo scenes/geometry-browser.html#PlaneGeometry */ class PlaneGeometry extends BufferGeometry { @@ -32905,7 +33246,7 @@ class Material extends EventDispatcher { * * This method can only be used when rendering with {@link WebGLRenderer}. The * recommended approach when customizing materials is to use `WebGPURenderer` with the new - * Node Material system and [TSL]{@link https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language}. + * Node Material system and [TSL](https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language). * * @param {{vertexShader:string,fragmentShader:string,uniforms:Object}} shaderobject - The object holds the uniforms and the vertex and fragment shader source. * @param {WebGLRenderer} renderer - A reference to the renderer. @@ -32944,7 +33285,7 @@ class Material extends EventDispatcher { if ( newValue === undefined ) { - console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + warn( `Material: parameter '${ key }' has value of undefined.` ); continue; } @@ -32953,7 +33294,7 @@ class Material extends EventDispatcher { if ( currentValue === undefined ) { - console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + warn( `Material: '${ key }' is not a property of THREE.${ this.type }.` ); continue; } @@ -33214,6 +33555,7 @@ class Material extends EventDispatcher { if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; if ( this.forceSinglePass === true ) data.forceSinglePass = true; + if ( this.allowOverride === false ) data.allowOverride = false; if ( this.wireframe === true ) data.wireframe = true; if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; @@ -33349,6 +33691,7 @@ class Material extends EventDispatcher { this.alphaToCoverage = source.alphaToCoverage; this.premultipliedAlpha = source.premultipliedAlpha; this.forceSinglePass = source.forceSinglePass; + this.allowOverride = source.allowOverride; this.visible = source.visible; @@ -33394,8 +33737,20 @@ class Material extends EventDispatcher { } -// Uniform Utilities +/** + * Provides utility functions for managing uniforms. + * + * @module UniformsUtils + */ +/** + * Clones the given uniform definitions by performing a deep-copy. That means + * if the value of a uniform refers to an object like a Vector3 or Texture, + * the cloned uniform will refer to a new object reference. + * + * @param {Object} src - An object representing uniform definitions. + * @return {Object} The cloned uniforms. + */ function cloneUniforms( src ) { const dst = {}; @@ -33415,7 +33770,7 @@ function cloneUniforms( src ) { if ( property.isRenderTargetTexture ) { - console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); dst[ u ][ p ] = null; } else { @@ -33442,6 +33797,14 @@ function cloneUniforms( src ) { } +/** + * Merges the given uniform definitions into a single object. Since the + * method internally uses cloneUniforms(), it performs a deep-copy when + * producing the merged uniform definitions. + * + * @param {Array} uniforms - An array of objects containing uniform definitions. + * @return {Object} The merged uniforms. + */ function mergeUniforms( uniforms ) { const merged = {}; @@ -33519,7 +33882,7 @@ var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 * - You can use the directive `#pragma unroll_loop_start` and `#pragma unroll_loop_end` * in order to unroll a `for` loop in GLSL by the shader preprocessor. The directive has * to be placed right above the loop. The loop formatting has to correspond to a defined standard. - * - The loop has to be [normalized]{@link https://en.wikipedia.org/wiki/Normalized_loop}. + * - The loop has to be [normalized](https://en.wikipedia.org/wiki/Normalized_loop). * - The loop variable has to be *i*. * - The value `UNROLLED_LOOP_INDEX` will be replaced with the explicitly * value of *i* for the given iteration and can be used in preprocessor @@ -33660,9 +34023,22 @@ class ShaderMaterial extends Material { this.wireframeLinewidth = 1; /** - * Define whether the material color is affected by global fog settings; `true` + * Defines whether the material color is affected by global fog settings; `true` * to pass fog uniforms to the shader. * + * Setting this property to `true` requires the definition of fog uniforms. It is + * recommended to use `UniformsUtils.merge()` to combine the custom shader uniforms + * with predefined fog uniforms. + * + * ```js + * const material = new ShaderMaterial( { + * uniforms: UniformsUtils.merge( [ UniformsLib[ 'fog' ], shaderUniforms ] ); + * vertexShader: vertexShader, + * fragmentShader: fragmentShader, + * fog: true + * } ); + * ``` + * * @type {boolean} * @default false */ @@ -33725,7 +34101,7 @@ class ShaderMaterial extends Material { }; /** - * If set, this calls [gl.bindAttribLocation]{@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation} + * If set, this calls [gl.bindAttribLocation](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation) * to bind a generic vertex index to an attribute variable. * * @type {string|undefined} @@ -33781,6 +34157,12 @@ class ShaderMaterial extends Material { this.glslVersion = source.glslVersion; + this.defaultAttributeValues = Object.assign( {}, source.defaultAttributeValues ); + + this.index0AttributeName = source.index0AttributeName; + + this.uniformsNeedUpdate = source.uniformsNeedUpdate; + return this; } @@ -35075,6 +35457,7 @@ class Triangle { * This material is not affected by lights. * * @augments Material + * @demo scenes/material-browser.html#MeshBasicMaterial */ class MeshBasicMaterial extends Material { @@ -35382,7 +35765,7 @@ class Mesh extends Object3D { * morph targets name, the value its attribute index. This member is `undefined` * by default and only set when morph targets are detected in the geometry. * - * @type {Object|undefined} + * @type {Object|undefined} * @default undefined */ this.morphTargetDictionary = undefined; @@ -35812,7 +36195,7 @@ var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; -var batching_pars_vertex = "#ifdef USE_BATCHING\n\t#if ! defined( GL_ANGLE_multi_draw )\n\t#define gl_DrawID _gl_DrawID\n\tuniform int _gl_DrawID;\n\t#endif\n\tuniform highp sampler2D batchingTexture;\n\tuniform highp usampler2D batchingIdTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n\tfloat getIndirectIndex( const in int i ) {\n\t\tint size = textureSize( batchingIdTexture, 0 ).x;\n\t\tint x = i % size;\n\t\tint y = i / size;\n\t\treturn float( texelFetch( batchingIdTexture, ivec2( x, y ), 0 ).r );\n\t}\n#endif\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec3 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb;\n\t}\n#endif"; +var batching_pars_vertex = "#ifdef USE_BATCHING\n\t#if ! defined( GL_ANGLE_multi_draw )\n\t#define gl_DrawID _gl_DrawID\n\tuniform int _gl_DrawID;\n\t#endif\n\tuniform highp sampler2D batchingTexture;\n\tuniform highp usampler2D batchingIdTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n\tfloat getIndirectIndex( const in int i ) {\n\t\tint size = textureSize( batchingIdTexture, 0 ).x;\n\t\tint x = i % size;\n\t\tint y = i / size;\n\t\treturn float( texelFetch( batchingIdTexture, ivec2( x, y ), 0 ).r );\n\t}\n#endif\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec4 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 );\n\t}\n#endif"; var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( getIndirectIndex( gl_DrawID ) );\n#endif"; @@ -35834,15 +36217,15 @@ var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 v var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; -var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; +var color_fragment = "#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#endif"; -var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; +var color_pars_fragment = "#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#endif"; -var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif"; +var color_pars_vertex = "#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec4 vColor;\n#endif"; -var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif"; +var color_vertex = "#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec4( 1.0 );\n#endif\n#ifdef USE_COLOR_ALPHA\n\tvColor *= color;\n#elif defined( USE_COLOR )\n\tvColor.rgb *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.rgb *= instanceColor.rgb;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvColor *= getBatchingColor( getIndirectIndex( gl_DrawID ) );\n#endif"; -var common$1 = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; +var common$1 = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; @@ -35860,9 +36243,9 @@ var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; var colorspace_pars_fragment = "vec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferEOTF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}"; -var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; +var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t\t#endif\n\t#endif\n#endif"; -var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; +var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n#endif"; var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif"; @@ -35888,7 +36271,7 @@ var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertM var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; -var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; +var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; @@ -35898,15 +36281,15 @@ var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; -var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; +var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.diffuseContribution = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.metalness = metalnessFactor;\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor;\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = vec3( 0.04 );\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.0001, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; -var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; +var lights_physical_pars_fragment = "uniform sampler2D dfgLUT;\nstruct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tvec3 diffuseContribution;\n\tvec3 specularColor;\n\tvec3 specularColorBlended;\n\tfloat roughness;\n\tfloat metalness;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t\tvec3 iridescenceFresnelDielectric;\n\t\tvec3 iridescenceFresnelMetallic;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn v;\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColorBlended;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transpose( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat rInv = 1.0 / ( roughness + 0.1 );\n\tfloat a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv;\n\tfloat b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv;\n\tfloat DG = exp( a * dotNV + b );\n\treturn saturate( DG );\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nvec3 BRDF_GGX_Multiscatter( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 singleScatter = BRDF_GGX( lightDir, viewDir, normal, material );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 dfgV = texture2D( dfgLUT, vec2( material.roughness, dotNV ) ).rg;\n\tvec2 dfgL = texture2D( dfgLUT, vec2( material.roughness, dotNL ) ).rg;\n\tvec3 FssEss_V = material.specularColorBlended * dfgV.x + material.specularF90 * dfgV.y;\n\tvec3 FssEss_L = material.specularColorBlended * dfgL.x + material.specularF90 * dfgL.y;\n\tfloat Ess_V = dfgV.x + dfgV.y;\n\tfloat Ess_L = dfgL.x + dfgL.y;\n\tfloat Ems_V = 1.0 - Ess_V;\n\tfloat Ems_L = 1.0 - Ess_L;\n\tvec3 Favg = material.specularColorBlended + ( 1.0 - material.specularColorBlended ) * 0.047619;\n\tvec3 Fms = FssEss_V * FssEss_L * Favg / ( 1.0 - Ems_V * Ems_L * Favg + EPSILON );\n\tfloat compensationFactor = Ems_V * Ems_L;\n\tvec3 multiScatter = Fms * compensationFactor;\n\treturn singleScatter + multiScatter;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t\t#ifdef USE_CLEARCOAT\n\t\t\tvec3 Ncc = geometryClearcoatNormal;\n\t\t\tvec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness );\n\t\t\tvec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat );\n\t\t\tvec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat );\n\t\t\tmat3 mInvClearcoat = mat3(\n\t\t\t\tvec3( t1Clearcoat.x, 0, t1Clearcoat.y ),\n\t\t\t\tvec3( 0, 1, 0 ),\n\t\t\t\tvec3( t1Clearcoat.z, 0, t1Clearcoat.w )\n\t\t\t);\n\t\t\tvec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y;\n\t\t\tclearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords );\n\t\t#endif\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n \n \t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n \n \t\tfloat sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n \t\tfloat sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness );\n \n \t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL );\n \n \t\tirradiance *= sheenEnergyComp;\n \n \t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX_Multiscatter( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseContribution );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution );\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tdiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectDiffuse += diffuse;\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI;\n \t#endif\n\tvec3 singleScatteringDielectric = vec3( 0.0 );\n\tvec3 multiScatteringDielectric = vec3( 0.0 );\n\tvec3 singleScatteringMetallic = vec3( 0.0 );\n\tvec3 multiScatteringMetallic = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnelDielectric, material.roughness, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceFresnelMetallic, material.roughness, singleScatteringMetallic, multiScatteringMetallic );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.roughness, singleScatteringMetallic, multiScatteringMetallic );\n\t#endif\n\tvec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness );\n\tvec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness );\n\tvec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric;\n\tvec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tvec3 indirectSpecular = radiance * singleScattering;\n\tindirectSpecular += multiScattering * cosineWeightedIrradiance;\n\tvec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tindirectSpecular *= sheenEnergyComp;\n\t\tindirectDiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectSpecular += indirectSpecular;\n\treflectedLight.indirectDiffuse += indirectDiffuse;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; -var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; +var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor );\n\t\tmaterial.iridescenceFresnel = mix( material.iridescenceFresnelDielectric, material.iridescenceFresnelMetallic, material.metalness );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; -var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; +var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\t#if defined( STANDARD ) || defined( LAMBERT ) || defined( PHONG )\n\t\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t\t#endif\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; -var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif"; +var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\t#if defined( LAMBERT ) || defined( PHONG )\n\t\tirradiance += iblIrradiance;\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif"; var logdepthbuf_fragment = "#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; @@ -35960,7 +36343,7 @@ var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; -var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; +var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\n\t\treturn depth * ( far - near ) - far;\n\t#else\n\t\treturn depth * ( near - far ) - near;\n\t#endif\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\t\n\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\treturn ( near * far ) / ( ( near - far ) * depth - near );\n\t#else\n\t\treturn ( near * far ) / ( ( far - near ) * depth - far );\n\t#endif\n}"; var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; @@ -35974,13 +36357,13 @@ var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUG var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; -var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\tfloat depth = unpackRGBAToDepth( texture2D( depths, uv ) );\n\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\treturn step( depth, compare );\n\t\t#else\n\t\t\treturn step( compare, depth );\n\t\t#endif\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow( sampler2D shadow, vec2 uv, float compare ) {\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\tfloat hard_shadow = step( distribution.x, compare );\n\t\t#else\n\t\t\tfloat hard_shadow = step( compare, distribution.x );\n\t\t#endif\n\t\tif ( hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif"; +var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\t\t\tuniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat interleavedGradientNoise( vec2 position ) {\n\t\t\treturn fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) );\n\t\t}\n\t\tvec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) {\n\t\t\tconst float goldenAngle = 2.399963229728653;\n\t\t\tfloat r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) );\n\t\t\tfloat theta = float( sampleIndex ) * goldenAngle + phi;\n\t\t\treturn vec2( cos( theta ), sin( theta ) ) * r;\n\t\t}\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\tshadowCoord.z += shadowBias;\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\t\tfloat radius = shadowRadius * texelSize.x;\n\t\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) )\n\t\t\t\t) * 0.2;\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg;\n\t\t\t\tfloat mean = distribution.x;\n\t\t\t\tfloat variance = distribution.y * distribution.y;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tfloat hard_shadow = step( mean, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tfloat hard_shadow = step( shadowCoord.z, mean );\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif ( hard_shadow == 1.0 ) {\n\t\t\t\t\tshadow = 1.0;\n\t\t\t\t} else {\n\t\t\t\t\tvariance = max( variance, 0.0000001 );\n\t\t\t\t\tfloat d = shadowCoord.z - mean;\n\t\t\t\t\tfloat p_max = variance / ( variance + d * d );\n\t\t\t\t\tp_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 );\n\t\t\t\t\tshadow = max( hard_shadow, p_max );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#else\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tfloat depth = texture2D( shadowMap, shadowCoord.xy ).r;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tshadow = step( depth, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tshadow = step( shadowCoord.z, depth );\n\t\t\t\t#endif\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\tfloat getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tfloat dp = ( shadowCameraNear * ( shadowCameraFar - viewSpaceZ ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp -= shadowBias;\n\t\t\t#else\n\t\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp += shadowBias;\n\t\t\t#endif\n\t\t\tfloat texelSize = shadowRadius / shadowMapSize.x;\n\t\t\tvec3 absDir = abs( bd3D );\n\t\t\tvec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 );\n\t\t\ttangent = normalize( cross( bd3D, tangent ) );\n\t\t\tvec3 bitangent = cross( bd3D, tangent );\n\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\tvec2 sample0 = vogelDiskSample( 0, 5, phi );\n\t\t\tvec2 sample1 = vogelDiskSample( 1, 5, phi );\n\t\t\tvec2 sample2 = vogelDiskSample( 2, 5, phi );\n\t\t\tvec2 sample3 = vogelDiskSample( 3, 5, phi );\n\t\t\tvec2 sample4 = vogelDiskSample( 4, 5, phi );\n\t\t\tshadow = (\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample0.x + bitangent * sample0.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample1.x + bitangent * sample1.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample2.x + bitangent * sample2.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample3.x + bitangent * sample3.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample4.x + bitangent * sample4.y ) * texelSize, dp ) )\n\t\t\t) * 0.2;\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\tfloat getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tfloat depth = textureCube( shadowMap, bd3D ).r;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tdepth = 1.0 - depth;\n\t\t\t#endif\n\t\t\tshadow = step( dp, depth );\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#endif\n\t#endif\n#endif"; var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; -var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}"; +var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0 && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}"; var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; @@ -35998,7 +36381,7 @@ var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = to var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 CineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; -var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; +var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseContribution, material.specularColorBlended, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t#else\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; @@ -36028,7 +36411,7 @@ const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\ const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}"; -const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; +const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = vec4( dist, 0.0, 0.0, 1.0 );\n}"; const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}"; @@ -36044,7 +36427,7 @@ const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_ const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; @@ -36052,19 +36435,19 @@ const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; -const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; +const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( normalize( normal ) * 0.5 + 0.5, diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; -const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n \n\t\toutgoingLight = outgoingLight + sheenSpecularDirect + sheenSpecularIndirect;\n \n \t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; -const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; @@ -36072,7 +36455,7 @@ const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include 0; // use PMREM if the user wants to blur the background - background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); + background = environments.get( background, usePMREM ); } @@ -37103,7 +37486,7 @@ function WebGLBindingStates( gl, attributes ) { let updateBuffers = false; - const state = getBindingState( geometry, program, material ); + const state = getBindingState( object, geometry, program, material ); if ( currentState !== state ) { @@ -37156,16 +37539,28 @@ function WebGLBindingStates( gl, attributes ) { } - function getBindingState( geometry, program, material ) { + function getBindingState( object, geometry, program, material ) { const wireframe = ( material.wireframe === true ); - let programMap = bindingStates[ geometry.id ]; + let objectMap = bindingStates[ geometry.id ]; + + if ( objectMap === undefined ) { + + objectMap = {}; + bindingStates[ geometry.id ] = objectMap; + + } + + // Each InstancedMesh requires unique binding states because it contains instanced attributes. + const objectId = ( object.isInstancedMesh === true ) ? object.id : 0; + + let programMap = objectMap[ objectId ]; if ( programMap === undefined ) { programMap = {}; - bindingStates[ geometry.id ] = programMap; + objectMap[ objectId ] = programMap; } @@ -37566,21 +37961,27 @@ function WebGLBindingStates( gl, attributes ) { for ( const geometryId in bindingStates ) { - const programMap = bindingStates[ geometryId ]; + const objectMap = bindingStates[ geometryId ]; - for ( const programId in programMap ) { + for ( const objectId in objectMap ) { - const stateMap = programMap[ programId ]; + const programMap = objectMap[ objectId ]; - for ( const wireframe in stateMap ) { + for ( const programId in programMap ) { - deleteVertexArrayObject( stateMap[ wireframe ].object ); + const stateMap = programMap[ programId ]; - delete stateMap[ wireframe ]; + for ( const wireframe in stateMap ) { - } + deleteVertexArrayObject( stateMap[ wireframe ].object ); - delete programMap[ programId ]; + delete stateMap[ wireframe ]; + + } + + delete programMap[ programId ]; + + } } @@ -37594,21 +37995,27 @@ function WebGLBindingStates( gl, attributes ) { if ( bindingStates[ geometry.id ] === undefined ) return; - const programMap = bindingStates[ geometry.id ]; + const objectMap = bindingStates[ geometry.id ]; - for ( const programId in programMap ) { + for ( const objectId in objectMap ) { - const stateMap = programMap[ programId ]; + const programMap = objectMap[ objectId ]; - for ( const wireframe in stateMap ) { + for ( const programId in programMap ) { - deleteVertexArrayObject( stateMap[ wireframe ].object ); + const stateMap = programMap[ programId ]; - delete stateMap[ wireframe ]; + for ( const wireframe in stateMap ) { - } + deleteVertexArrayObject( stateMap[ wireframe ].object ); - delete programMap[ programId ]; + delete stateMap[ wireframe ]; + + } + + delete programMap[ programId ]; + + } } @@ -37620,26 +38027,73 @@ function WebGLBindingStates( gl, attributes ) { for ( const geometryId in bindingStates ) { - const programMap = bindingStates[ geometryId ]; + const objectMap = bindingStates[ geometryId ]; + + for ( const objectId in objectMap ) { - if ( programMap[ program.id ] === undefined ) continue; + const programMap = objectMap[ objectId ]; - const stateMap = programMap[ program.id ]; + if ( programMap[ program.id ] === undefined ) continue; - for ( const wireframe in stateMap ) { + const stateMap = programMap[ program.id ]; - deleteVertexArrayObject( stateMap[ wireframe ].object ); + for ( const wireframe in stateMap ) { + + deleteVertexArrayObject( stateMap[ wireframe ].object ); + + delete stateMap[ wireframe ]; + + } - delete stateMap[ wireframe ]; + delete programMap[ program.id ]; } - delete programMap[ program.id ]; + } + + } + + function releaseStatesOfObject( object ) { + + for ( const geometryId in bindingStates ) { + + const objectMap = bindingStates[ geometryId ]; + + const objectId = ( object.isInstancedMesh === true ) ? object.id : 0; + + const programMap = objectMap[ objectId ]; + + if ( programMap === undefined ) continue; + + for ( const programId in programMap ) { + + const stateMap = programMap[ programId ]; + + for ( const wireframe in stateMap ) { + + deleteVertexArrayObject( stateMap[ wireframe ].object ); + + delete stateMap[ wireframe ]; + + } + + delete programMap[ programId ]; + + } + + delete objectMap[ objectId ]; + + if ( Object.keys( objectMap ).length === 0 ) { + + delete bindingStates[ geometryId ]; + + } } } + function reset() { resetDefaultState(); @@ -37669,6 +38123,7 @@ function WebGLBindingStates( gl, attributes ) { resetDefaultState: resetDefaultState, dispose: dispose, releaseStatesOfGeometry: releaseStatesOfGeometry, + releaseStatesOfObject: releaseStatesOfObject, releaseStatesOfProgram: releaseStatesOfProgram, initAttributes: initAttributes, @@ -37852,7 +38307,7 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { if ( maxPrecision !== precision ) { - console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); + warn( 'WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); precision = maxPrecision; } @@ -37870,9 +38325,8 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); - const vertexTextures = maxVertexTextures > 0; - const maxSamples = gl.getParameter( gl.MAX_SAMPLES ); + const samples = gl.getParameter( gl.SAMPLES ); return { @@ -37898,9 +38352,9 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { maxVaryings: maxVaryings, maxFragmentUniforms: maxFragmentUniforms, - vertexTextures: vertexTextures, + maxSamples: maxSamples, - maxSamples: maxSamples + samples: samples }; @@ -38072,6 +38526,10 @@ function WebGLClipping( properties ) { } +const _position$1 = /*@__PURE__*/ new Vector3(); +const _quaternion = /*@__PURE__*/ new Quaternion(); +const _scale = /*@__PURE__*/ new Vector3(); + /** * Abstract base class for cameras. This class should always be inherited * when you build a new camera. @@ -38177,7 +38635,19 @@ class Camera extends Object3D { super.updateMatrixWorld( force ); - this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + // exclude scale from view matrix to be glTF conform + + this.matrixWorld.decompose( _position$1, _quaternion, _scale ); + + if ( _scale.x === 1 && _scale.y === 1 && _scale.z === 1 ) { + + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + + } else { + + this.matrixWorldInverse.compose( _position$1, _quaternion, _scale.set( 1, 1, 1 ) ).invert(); + + } } @@ -38185,7 +38655,19 @@ class Camera extends Object3D { super.updateWorldMatrix( updateParents, updateChildren ); - this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + // exclude scale from view matrix to be glTF conform + + this.matrixWorld.decompose( _position$1, _quaternion, _scale ); + + if ( _scale.x === 1 && _scale.y === 1 && _scale.z === 1 ) { + + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + + } else { + + this.matrixWorldInverse.compose( _position$1, _quaternion, _scale.set( 1, 1, 1 ) ).invert(); + + } } @@ -38197,12 +38679,254 @@ class Camera extends Object3D { } +/** + * Camera that uses [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection). + * + * In this projection mode, an object's size in the rendered image stays + * constant regardless of its distance from the camera. This can be useful + * for rendering 2D scenes and UI elements, amongst other things. + * + * ```js + * const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 ); + * scene.add( camera ); + * ``` + * + * @augments Camera + */ +class OrthographicCamera extends Camera { + + /** + * Constructs a new orthographic camera. + * + * @param {number} [left=-1] - The left plane of the camera's frustum. + * @param {number} [right=1] - The right plane of the camera's frustum. + * @param {number} [top=1] - The top plane of the camera's frustum. + * @param {number} [bottom=-1] - The bottom plane of the camera's frustum. + * @param {number} [near=0.1] - The camera's near plane. + * @param {number} [far=2000] - The camera's far plane. + */ + constructor( left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000 ) { + + super(); + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isOrthographicCamera = true; + + this.type = 'OrthographicCamera'; + + /** + * The zoom factor of the camera. + * + * @type {number} + * @default 1 + */ + this.zoom = 1; + + /** + * Represents the frustum window specification. This property should not be edited + * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}. + * + * @type {?Object} + * @default null + */ + this.view = null; + + /** + * The left plane of the camera's frustum. + * + * @type {number} + * @default -1 + */ + this.left = left; + + /** + * The right plane of the camera's frustum. + * + * @type {number} + * @default 1 + */ + this.right = right; + + /** + * The top plane of the camera's frustum. + * + * @type {number} + * @default 1 + */ + this.top = top; + + /** + * The bottom plane of the camera's frustum. + * + * @type {number} + * @default -1 + */ + this.bottom = bottom; + + /** + * The camera's near plane. The valid range is greater than `0` + * and less than the current value of {@link OrthographicCamera#far}. + * + * Note that, unlike for the {@link PerspectiveCamera}, `0` is a + * valid value for an orthographic camera's near plane. + * + * @type {number} + * @default 0.1 + */ + this.near = near; + + /** + * The camera's far plane. Must be greater than the + * current value of {@link OrthographicCamera#near}. + * + * @type {number} + * @default 2000 + */ + this.far = far; + + this.updateProjectionMatrix(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; + + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); + + return this; + + } + + /** + * Sets an offset in a larger frustum. This is useful for multi-window or + * multi-monitor/multi-machine setups. + * + * @param {number} fullWidth - The full width of multiview setup. + * @param {number} fullHeight - The full height of multiview setup. + * @param {number} x - The horizontal offset of the subcamera. + * @param {number} y - The vertical offset of the subcamera. + * @param {number} width - The width of subcamera. + * @param {number} height - The height of subcamera. + * @see {@link PerspectiveCamera#setViewOffset} + */ + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { + + if ( this.view === null ) { + + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + + } + + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; + + this.updateProjectionMatrix(); + + } + + /** + * Removes the view offset from the projection matrix. + */ + clearViewOffset() { + + if ( this.view !== null ) { + + this.view.enabled = false; + + } + + this.updateProjectionMatrix(); + + } + + /** + * Updates the camera's projection matrix. Must be called after any change of + * camera properties. + */ + updateProjectionMatrix() { + + const dx = ( this.right - this.left ) / ( 2 * this.zoom ); + const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); + const cx = ( this.right + this.left ) / 2; + const cy = ( this.top + this.bottom ) / 2; + + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; + + if ( this.view !== null && this.view.enabled ) { + + const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; + const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; + + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; + + } + + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem, this.reversedDepth ); + + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; + + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + + return data; + + } + +} + const _v3 = /*@__PURE__*/ new Vector3(); const _minTarget = /*@__PURE__*/ new Vector2(); const _maxTarget = /*@__PURE__*/ new Vector2(); /** - * Camera that uses [perspective projection]{@link https://en.wikipedia.org/wiki/Perspective_(graphical)}. + * Camera that uses [perspective projection](https://en.wikipedia.org/wiki/Perspective_(graphical)). * * This projection mode is designed to mimic the way the human eye sees. It * is the most common projection mode used for rendering a 3D scene. @@ -38598,838 +39322,20 @@ class PerspectiveCamera extends Camera { } -const fov = -90; // negative fov is not an error -const aspect = 1; - -/** - * A special type of camera that is positioned in 3D space to render its surroundings into a - * cube render target. The render target can then be used as an environment map for rendering - * realtime reflections in your scene. - * - * ```js - * // Create cube render target - * const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } ); - * - * // Create cube camera - * const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget ); - * scene.add( cubeCamera ); - * - * // Create car - * const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } ); - * const car = new THREE.Mesh( carGeometry, chromeMaterial ); - * scene.add( car ); - * - * // Update the render target cube - * car.visible = false; - * cubeCamera.position.copy( car.position ); - * cubeCamera.update( renderer, scene ); - * - * // Render the scene - * car.visible = true; - * renderer.render( scene, camera ); - * ``` - * - * @augments Object3D - */ -class CubeCamera extends Object3D { - - /** - * Constructs a new cube camera. - * - * @param {number} near - The camera's near plane. - * @param {number} far - The camera's far plane. - * @param {WebGLCubeRenderTarget} renderTarget - The cube render target. - */ - constructor( near, far, renderTarget ) { - - super(); - - this.type = 'CubeCamera'; - - /** - * A reference to the cube render target. - * - * @type {WebGLCubeRenderTarget} - */ - this.renderTarget = renderTarget; - - /** - * The current active coordinate system. - * - * @type {?(WebGLCoordinateSystem|WebGPUCoordinateSystem)} - * @default null - */ - this.coordinateSystem = null; - - /** - * The current active mipmap level - * - * @type {number} - * @default 0 - */ - this.activeMipmapLevel = 0; - - const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); - cameraPX.layers = this.layers; - this.add( cameraPX ); - - const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); - cameraNX.layers = this.layers; - this.add( cameraNX ); - - const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); - cameraPY.layers = this.layers; - this.add( cameraPY ); - - const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); - cameraNY.layers = this.layers; - this.add( cameraNY ); - - const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraPZ.layers = this.layers; - this.add( cameraPZ ); - - const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); - cameraNZ.layers = this.layers; - this.add( cameraNZ ); - - } - - /** - * Must be called when the coordinate system of the cube camera is changed. - */ - updateCoordinateSystem() { - - const coordinateSystem = this.coordinateSystem; - - const cameras = this.children.concat(); - - const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; - - for ( const camera of cameras ) this.remove( camera ); - - if ( coordinateSystem === WebGLCoordinateSystem ) { - - cameraPX.up.set( 0, 1, 0 ); - cameraPX.lookAt( 1, 0, 0 ); - - cameraNX.up.set( 0, 1, 0 ); - cameraNX.lookAt( -1, 0, 0 ); - - cameraPY.up.set( 0, 0, -1 ); - cameraPY.lookAt( 0, 1, 0 ); - - cameraNY.up.set( 0, 0, 1 ); - cameraNY.lookAt( 0, -1, 0 ); - - cameraPZ.up.set( 0, 1, 0 ); - cameraPZ.lookAt( 0, 0, 1 ); - - cameraNZ.up.set( 0, 1, 0 ); - cameraNZ.lookAt( 0, 0, -1 ); - - } else if ( coordinateSystem === WebGPUCoordinateSystem ) { - - cameraPX.up.set( 0, -1, 0 ); - cameraPX.lookAt( -1, 0, 0 ); - - cameraNX.up.set( 0, -1, 0 ); - cameraNX.lookAt( 1, 0, 0 ); - - cameraPY.up.set( 0, 0, 1 ); - cameraPY.lookAt( 0, 1, 0 ); - - cameraNY.up.set( 0, 0, -1 ); - cameraNY.lookAt( 0, -1, 0 ); - - cameraPZ.up.set( 0, -1, 0 ); - cameraPZ.lookAt( 0, 0, 1 ); - - cameraNZ.up.set( 0, -1, 0 ); - cameraNZ.lookAt( 0, 0, -1 ); - - } else { - - throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); - - } - - for ( const camera of cameras ) { - - this.add( camera ); - - camera.updateMatrixWorld(); - - } - - } - - /** - * Calling this method will render the given scene with the given renderer - * into the cube render target of the camera. - * - * @param {(Renderer|WebGLRenderer)} renderer - The renderer. - * @param {Scene} scene - The scene to render. - */ - update( renderer, scene ) { - - if ( this.parent === null ) this.updateMatrixWorld(); - - const { renderTarget, activeMipmapLevel } = this; - - if ( this.coordinateSystem !== renderer.coordinateSystem ) { - - this.coordinateSystem = renderer.coordinateSystem; - - this.updateCoordinateSystem(); - - } - - const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; - - const currentRenderTarget = renderer.getRenderTarget(); - const currentActiveCubeFace = renderer.getActiveCubeFace(); - const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); - - const currentXrEnabled = renderer.xr.enabled; - - renderer.xr.enabled = false; - - const generateMipmaps = renderTarget.texture.generateMipmaps; - - renderTarget.texture.generateMipmaps = false; - - renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); - renderer.render( scene, cameraPX ); - - renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); - renderer.render( scene, cameraNX ); - - renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); - renderer.render( scene, cameraPY ); - - renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); - renderer.render( scene, cameraNY ); - - renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); - renderer.render( scene, cameraPZ ); - - // mipmaps are generated during the last call of render() - // at this point, all sides of the cube render target are defined - - renderTarget.texture.generateMipmaps = generateMipmaps; - - renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); - renderer.render( scene, cameraNZ ); - - renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); - - renderer.xr.enabled = currentXrEnabled; - - renderTarget.texture.needsPMREMUpdate = true; - - } - -} - -/** - * Creates a cube texture made up of six images. - * - * ```js - * const loader = new THREE.CubeTextureLoader(); - * loader.setPath( 'textures/cube/pisa/' ); - * - * const textureCube = loader.load( [ - * 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' - * ] ); - * - * const material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } ); - * ``` - * - * @augments Texture - */ -class CubeTexture extends Texture { - - /** - * Constructs a new cube texture. - * - * @param {Array} [images=[]] - An array holding a image for each side of a cube. - * @param {number} [mapping=CubeReflectionMapping] - The texture mapping. - * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value. - * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value. - * @param {number} [magFilter=LinearFilter] - The mag filter value. - * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value. - * @param {number} [format=RGBAFormat] - The texture format. - * @param {number} [type=UnsignedByteType] - The texture type. - * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value. - * @param {string} [colorSpace=NoColorSpace] - The color space value. - */ - constructor( images = [], mapping = CubeReflectionMapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { - - super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); - - /** - * This flag can be used for type testing. - * - * @type {boolean} - * @readonly - * @default true - */ - this.isCubeTexture = true; - - /** - * If set to `true`, the texture is flipped along the vertical axis when - * uploaded to the GPU. - * - * Overwritten and set to `false` by default. - * - * @type {boolean} - * @default false - */ - this.flipY = false; - - } - - /** - * Alias for {@link CubeTexture#image}. - * - * @type {Array} - */ - get images() { - - return this.image; - - } - - set images( value ) { - - this.image = value; - - } - -} - -/** - * A cube render target used in context of {@link WebGLRenderer}. - * - * @augments WebGLRenderTarget - */ -class WebGLCubeRenderTarget extends WebGLRenderTarget { - - /** - * Constructs a new cube render target. - * - * @param {number} [size=1] - The size of the render target. - * @param {RenderTarget~Options} [options] - The configuration object. - */ - constructor( size = 1, options = {} ) { - - super( size, size, options ); - - /** - * This flag can be used for type testing. - * - * @type {boolean} - * @readonly - * @default true - */ - this.isWebGLCubeRenderTarget = true; - - const image = { width: size, height: size, depth: 1 }; - const images = [ image, image, image, image, image, image ]; - - /** - * Overwritten with a different texture type. - * - * @type {DataArrayTexture} - */ - this.texture = new CubeTexture( images ); - this._setTextureOptions( options ); - - // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) - // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, - // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. - - // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped - // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture - // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). - - this.texture.isRenderTargetTexture = true; - - } - - /** - * Converts the given equirectangular texture to a cube map. - * - * @param {WebGLRenderer} renderer - The renderer. - * @param {Texture} texture - The equirectangular texture. - * @return {WebGLCubeRenderTarget} A reference to this cube render target. - */ - fromEquirectangularTexture( renderer, texture ) { - - this.texture.type = texture.type; - this.texture.colorSpace = texture.colorSpace; - - this.texture.generateMipmaps = texture.generateMipmaps; - this.texture.minFilter = texture.minFilter; - this.texture.magFilter = texture.magFilter; - - const shader = { - - uniforms: { - tEquirect: { value: null }, - }, - - vertexShader: /* glsl */` - - varying vec3 vWorldDirection; - - vec3 transformDirection( in vec3 dir, in mat4 matrix ) { - - return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); - - } - - void main() { - - vWorldDirection = transformDirection( position, modelMatrix ); - - #include - #include - - } - `, - - fragmentShader: /* glsl */` - - uniform sampler2D tEquirect; - - varying vec3 vWorldDirection; - - #include - - void main() { - - vec3 direction = normalize( vWorldDirection ); - - vec2 sampleUV = equirectUv( direction ); - - gl_FragColor = texture2D( tEquirect, sampleUV ); - - } - ` - }; - - const geometry = new BoxGeometry( 5, 5, 5 ); - - const material = new ShaderMaterial( { - - name: 'CubemapFromEquirect', - - uniforms: cloneUniforms( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader, - side: BackSide, - blending: NoBlending - - } ); - - material.uniforms.tEquirect.value = texture; - - const mesh = new Mesh( geometry, material ); - - const currentMinFilter = texture.minFilter; - - // Avoid blurred poles - if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; - - const camera = new CubeCamera( 1, 10, this ); - camera.update( renderer, mesh ); - - texture.minFilter = currentMinFilter; - - mesh.geometry.dispose(); - mesh.material.dispose(); - - return this; - - } - - /** - * Clears this cube render target. - * - * @param {WebGLRenderer} renderer - The renderer. - * @param {boolean} [color=true] - Whether the color buffer should be cleared or not. - * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not. - * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. - */ - clear( renderer, color = true, depth = true, stencil = true ) { - - const currentRenderTarget = renderer.getRenderTarget(); - - for ( let i = 0; i < 6; i ++ ) { - - renderer.setRenderTarget( this, i ); - - renderer.clear( color, depth, stencil ); - - } - - renderer.setRenderTarget( currentRenderTarget ); - - } - -} - -function WebGLCubeMaps( renderer ) { - - let cubemaps = new WeakMap(); - - function mapTextureMapping( texture, mapping ) { - - if ( mapping === EquirectangularReflectionMapping ) { - - texture.mapping = CubeReflectionMapping; - - } else if ( mapping === EquirectangularRefractionMapping ) { - - texture.mapping = CubeRefractionMapping; - - } - - return texture; - - } - - function get( texture ) { - - if ( texture && texture.isTexture ) { - - const mapping = texture.mapping; - - if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { - - if ( cubemaps.has( texture ) ) { - - const cubemap = cubemaps.get( texture ).texture; - return mapTextureMapping( cubemap, texture.mapping ); - - } else { - - const image = texture.image; - - if ( image && image.height > 0 ) { - - const renderTarget = new WebGLCubeRenderTarget( image.height ); - renderTarget.fromEquirectangularTexture( renderer, texture ); - cubemaps.set( texture, renderTarget ); - - texture.addEventListener( 'dispose', onTextureDispose ); - - return mapTextureMapping( renderTarget.texture, texture.mapping ); - - } else { - - // image not yet ready. try the conversion next frame - - return null; - - } - - } - - } - - } - - return texture; - - } - - function onTextureDispose( event ) { - - const texture = event.target; - - texture.removeEventListener( 'dispose', onTextureDispose ); - - const cubemap = cubemaps.get( texture ); - - if ( cubemap !== undefined ) { - - cubemaps.delete( texture ); - cubemap.dispose(); - - } - - } - - function dispose() { - - cubemaps = new WeakMap(); - - } - - return { - get: get, - dispose: dispose - }; - -} - -/** - * Camera that uses [orthographic projection]{@link https://en.wikipedia.org/wiki/Orthographic_projection}. - * - * In this projection mode, an object's size in the rendered image stays - * constant regardless of its distance from the camera. This can be useful - * for rendering 2D scenes and UI elements, amongst other things. - * - * ```js - * const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 ); - * scene.add( camera ); - * ``` - * - * @augments Camera - */ -class OrthographicCamera extends Camera { - - /** - * Constructs a new orthographic camera. - * - * @param {number} [left=-1] - The left plane of the camera's frustum. - * @param {number} [right=1] - The right plane of the camera's frustum. - * @param {number} [top=1] - The top plane of the camera's frustum. - * @param {number} [bottom=-1] - The bottom plane of the camera's frustum. - * @param {number} [near=0.1] - The camera's near plane. - * @param {number} [far=2000] - The camera's far plane. - */ - constructor( left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000 ) { - - super(); - - /** - * This flag can be used for type testing. - * - * @type {boolean} - * @readonly - * @default true - */ - this.isOrthographicCamera = true; - - this.type = 'OrthographicCamera'; - - /** - * The zoom factor of the camera. - * - * @type {number} - * @default 1 - */ - this.zoom = 1; - - /** - * Represents the frustum window specification. This property should not be edited - * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}. - * - * @type {?Object} - * @default null - */ - this.view = null; - - /** - * The left plane of the camera's frustum. - * - * @type {number} - * @default -1 - */ - this.left = left; - - /** - * The right plane of the camera's frustum. - * - * @type {number} - * @default 1 - */ - this.right = right; - - /** - * The top plane of the camera's frustum. - * - * @type {number} - * @default 1 - */ - this.top = top; - - /** - * The bottom plane of the camera's frustum. - * - * @type {number} - * @default -1 - */ - this.bottom = bottom; - - /** - * The camera's near plane. The valid range is greater than `0` - * and less than the current value of {@link OrthographicCamera#far}. - * - * Note that, unlike for the {@link PerspectiveCamera}, `0` is a - * valid value for an orthographic camera's near plane. - * - * @type {number} - * @default 0.1 - */ - this.near = near; - - /** - * The camera's far plane. Must be greater than the - * current value of {@link OrthographicCamera#near}. - * - * @type {number} - * @default 2000 - */ - this.far = far; - - this.updateProjectionMatrix(); - - } - - copy( source, recursive ) { - - super.copy( source, recursive ); - - this.left = source.left; - this.right = source.right; - this.top = source.top; - this.bottom = source.bottom; - this.near = source.near; - this.far = source.far; - - this.zoom = source.zoom; - this.view = source.view === null ? null : Object.assign( {}, source.view ); - - return this; - - } - - /** - * Sets an offset in a larger frustum. This is useful for multi-window or - * multi-monitor/multi-machine setups. - * - * @param {number} fullWidth - The full width of multiview setup. - * @param {number} fullHeight - The full height of multiview setup. - * @param {number} x - The horizontal offset of the subcamera. - * @param {number} y - The vertical offset of the subcamera. - * @param {number} width - The width of subcamera. - * @param {number} height - The height of subcamera. - * @see {@link PerspectiveCamera#setViewOffset} - */ - setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - - if ( this.view === null ) { - - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; - - } - - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; - - this.updateProjectionMatrix(); - - } - - /** - * Removes the view offset from the projection matrix. - */ - clearViewOffset() { - - if ( this.view !== null ) { - - this.view.enabled = false; - - } - - this.updateProjectionMatrix(); - - } - - /** - * Updates the camera's projection matrix. Must be called after any change of - * camera properties. - */ - updateProjectionMatrix() { - - const dx = ( this.right - this.left ) / ( 2 * this.zoom ); - const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - const cx = ( this.right + this.left ) / 2; - const cy = ( this.top + this.bottom ) / 2; - - let left = cx - dx; - let right = cx + dx; - let top = cy + dy; - let bottom = cy - dy; - - if ( this.view !== null && this.view.enabled ) { - - const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; - const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; - - left += scaleW * this.view.offsetX; - right = left + scaleW * this.view.width; - top -= scaleH * this.view.offsetY; - bottom = top - scaleH * this.view.height; - - } - - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem, this.reversedDepth ); - - this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - - } - - toJSON( meta ) { - - const data = super.toJSON( meta ); - - data.object.zoom = this.zoom; - data.object.left = this.left; - data.object.right = this.right; - data.object.top = this.top; - data.object.bottom = this.bottom; - data.object.near = this.near; - data.object.far = this.far; - - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - - return data; - - } - -} - const LOD_MIN = 4; -// The standard deviations (radians) associated with the extra mips. These are -// chosen to approximate a Trowbridge-Reitz distribution function times the -// geometric shadowing function. These sigma values squared must match the -// variance #defines in cube_uv_reflection_fragment.glsl.js. +// The standard deviations (radians) associated with the extra mips. +// Used for scene blur in fromScene() method. const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; // The maximum length of the blur for loop. Smaller sigmas will use fewer // samples and exit early, but not recompile the shader. +// Used for scene blur in fromScene() method. const MAX_SAMPLES = 20; +// GGX VNDF importance sampling configuration +const GGX_SAMPLES = 256; + const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); const _clearColor = /*@__PURE__*/ new Color(); let _oldTarget = null; @@ -39437,24 +39343,6 @@ let _oldActiveCubeFace = 0; let _oldActiveMipmapLevel = 0; let _oldXrEnabled = false; -// Golden Ratio -const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; -const INV_PHI = 1 / PHI; - -// Vertices of a dodecahedron (except the opposites, which represent the -// same axis), used as axis directions evenly spread on a sphere. -const _axisDirections = [ - /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), - /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), - /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), - /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), - /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), - /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), - /*@__PURE__*/ new Vector3( -1, 1, -1 ), - /*@__PURE__*/ new Vector3( 1, 1, -1 ), - /*@__PURE__*/ new Vector3( -1, 1, 1 ), - /*@__PURE__*/ new Vector3( 1, 1, 1 ) ]; - const _origin = /*@__PURE__*/ new Vector3(); /** @@ -39468,9 +39356,11 @@ const _origin = /*@__PURE__*/ new Vector3(); * higher roughness levels. In this way we maintain resolution to smoothly * interpolate diffuse lighting while limiting sampling computation. * - * Paper: Fast, Accurate Image-Based Lighting: - * {@link https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view} -*/ + * The prefiltering uses GGX VNDF (Visible Normal Distribution Function) + * importance sampling based on "Sampling the GGX Distribution of Visible Normals" + * (Heitz, 2018) to generate environment maps that accurately match the GGX BRDF + * used in material rendering for physically-based image-based lighting. + */ class PMREMGenerator { /** @@ -39485,15 +39375,17 @@ class PMREMGenerator { this._lodMax = 0; this._cubeSize = 0; - this._lodPlanes = []; this._sizeLods = []; this._sigmas = []; + this._lodMeshes = []; + + this._backgroundBox = null; - this._blurMaterial = null; this._cubemapMaterial = null; this._equirectMaterial = null; - this._compileMaterial( this._blurMaterial ); + this._blurMaterial = null; + this._ggxMaterial = null; } @@ -39509,7 +39401,7 @@ class PMREMGenerator { * @param {number} [far=100] - The far plane distance. * @param {Object} [options={}] - The configuration options. * @param {number} [options.size=256] - The texture size of the PMREM. - * @param {Vector3} [options.renderTarget=origin] - The position of the internal cube camera that renders the scene. + * @param {Vector3} [options.position=origin] - The position of the internal cube camera that renders the scene. * @return {WebGLRenderTarget} The resulting PMREM. */ fromScene( scene, sigma = 0, near = 0.1, far = 100, options = {} ) { @@ -39618,6 +39510,13 @@ class PMREMGenerator { if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); + if ( this._backgroundBox !== null ) { + + this._backgroundBox.geometry.dispose(); + this._backgroundBox.material.dispose(); + + } + } // private interface @@ -39632,12 +39531,13 @@ class PMREMGenerator { _dispose() { if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); + if ( this._ggxMaterial !== null ) this._ggxMaterial.dispose(); if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); - for ( let i = 0; i < this._lodPlanes.length; i ++ ) { + for ( let i = 0; i < this._lodMeshes.length; i ++ ) { - this._lodPlanes[ i ].dispose(); + this._lodMeshes[ i ].geometry.dispose(); } @@ -39709,9 +39609,10 @@ class PMREMGenerator { this._pingPongRenderTarget = _createRenderTarget( width, height, params ); const { _lodMax } = this; - ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); + ( { lodMeshes: this._lodMeshes, sizeLods: this._sizeLods, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); this._blurMaterial = _getBlurShader( _lodMax, width, height ); + this._ggxMaterial = _getGGXShader( _lodMax, width, height ); } @@ -39721,8 +39622,8 @@ class PMREMGenerator { _compileMaterial( material ) { - const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); - this._renderer.compile( tmpMesh, _flatCamera ); + const mesh = new Mesh( new BufferGeometry(), material ); + this._renderer.compile( mesh, _flatCamera ); } @@ -39753,16 +39654,25 @@ class PMREMGenerator { } - const backgroundMaterial = new MeshBasicMaterial( { - name: 'PMREM.Background', - side: BackSide, - depthWrite: false, - depthTest: false, - } ); + if ( this._backgroundBox === null ) { + + this._backgroundBox = new Mesh( + new BoxGeometry(), + new MeshBasicMaterial( { + name: 'PMREM.Background', + side: BackSide, + depthWrite: false, + depthTest: false, + } ) + ); + + } - const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); + const backgroundBox = this._backgroundBox; + const backgroundMaterial = backgroundBox.material; let useSolidColor = false; + const background = scene.background; if ( background ) { @@ -39823,9 +39733,6 @@ class PMREMGenerator { } - backgroundBox.geometry.dispose(); - backgroundBox.material.dispose(); - renderer.toneMapping = toneMapping; renderer.autoClear = originalAutoClear; scene.background = background; @@ -39859,7 +39766,9 @@ class PMREMGenerator { } const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; - const mesh = new Mesh( this._lodPlanes[ 0 ], material ); + + const mesh = this._lodMeshes[ 0 ]; + mesh.material = material; const uniforms = material.uniforms; @@ -39879,15 +39788,13 @@ class PMREMGenerator { const renderer = this._renderer; const autoClear = renderer.autoClear; renderer.autoClear = false; - const n = this._lodPlanes.length; - - for ( let i = 1; i < n; i ++ ) { - const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); + const n = this._lodMeshes.length; - const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; + // Use GGX VNDF importance sampling + for ( let i = 1; i < n; i ++ ) { - this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); + this._applyGGXFilter( cubeUVRenderTarget, i - 1, i ); } @@ -39895,6 +39802,63 @@ class PMREMGenerator { } + /** + * Applies GGX VNDF importance sampling filter to generate a prefiltered environment map. + * Uses Monte Carlo integration with VNDF importance sampling to accurately represent the + * GGX BRDF for physically-based rendering. Reads from the previous LOD level and + * applies incremental roughness filtering to avoid over-blurring. + * + * @private + * @param {WebGLRenderTarget} cubeUVRenderTarget + * @param {number} lodIn - Source LOD level to read from + * @param {number} lodOut - Target LOD level to write to + */ + _applyGGXFilter( cubeUVRenderTarget, lodIn, lodOut ) { + + const renderer = this._renderer; + const pingPongRenderTarget = this._pingPongRenderTarget; + + const ggxMaterial = this._ggxMaterial; + const ggxMesh = this._lodMeshes[ lodOut ]; + ggxMesh.material = ggxMaterial; + + const ggxUniforms = ggxMaterial.uniforms; + + // Calculate incremental roughness between LOD levels + const targetRoughness = lodOut / ( this._lodMeshes.length - 1 ); + const sourceRoughness = lodIn / ( this._lodMeshes.length - 1 ); + const incrementalRoughness = Math.sqrt( targetRoughness * targetRoughness - sourceRoughness * sourceRoughness ); + + // Apply blur strength mapping for better quality across the roughness range + const blurStrength = 0.0 + targetRoughness * 1.25; + const adjustedRoughness = incrementalRoughness * blurStrength; + + // Calculate viewport position based on output LOD level + const { _lodMax } = this; + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); + + // Read from previous LOD with incremental roughness + ggxUniforms[ 'envMap' ].value = cubeUVRenderTarget.texture; + ggxUniforms[ 'roughness' ].value = adjustedRoughness; + ggxUniforms[ 'mipInt' ].value = _lodMax - lodIn; // Sample from input LOD + + _setViewport( pingPongRenderTarget, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( pingPongRenderTarget ); + renderer.render( ggxMesh, _flatCamera ); + + // Copy from pingPong back to cubeUV (simple direct copy) + ggxUniforms[ 'envMap' ].value = pingPongRenderTarget.texture; + ggxUniforms[ 'roughness' ].value = 0.0; // Direct copy + ggxUniforms[ 'mipInt' ].value = _lodMax - lodOut; // Read from the level we just wrote + + _setViewport( cubeUVRenderTarget, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( cubeUVRenderTarget ); + renderer.render( ggxMesh, _flatCamera ); + + } + /** * This is a two-pass Gaussian blur for a cubemap. Normally this is done * vertically and horizontally, but this breaks down on a cube. Here we apply @@ -39902,6 +39866,8 @@ class PMREMGenerator { * the poles) to approximate the orthogonally-separable blur. It is least * accurate at the poles, but still does a decent job. * + * Used for initial scene blur in fromScene() method when sigma > 0. + * * @private * @param {WebGLRenderTarget} cubeUVRenderTarget * @param {number} lodIn @@ -39940,7 +39906,7 @@ class PMREMGenerator { if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { - console.error( + error( 'blur direction must be either latitudinal or longitudinal!' ); } @@ -39948,7 +39914,9 @@ class PMREMGenerator { // Number of standard deviations at which to cut off the discrete approximation. const STANDARD_DEVIATIONS = 3; - const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); + const blurMesh = this._lodMeshes[ lodOut ]; + blurMesh.material = blurMaterial; + const blurUniforms = blurMaterial.uniforms; const pixels = this._sizeLods[ lodIn ] - 1; @@ -39958,7 +39926,7 @@ class PMREMGenerator { if ( samples > MAX_SAMPLES ) { - console.warn( `sigmaRadians, ${ + warn( `sigmaRadians, ${ sigmaRadians}, is too large and will clip, as it requested ${ samples} samples when the maximum is set to ${MAX_SAMPLES}` ); @@ -40022,9 +39990,9 @@ class PMREMGenerator { function _createPlanes( lodMax ) { - const lodPlanes = []; const sizeLods = []; const sigmas = []; + const lodMeshes = []; let lod = lodMax; @@ -40086,7 +40054,7 @@ function _createPlanes( lodMax ) { planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); - lodPlanes.push( planes ); + lodMeshes.push( new Mesh( planes, null ) ); if ( lod > LOD_MIN ) { @@ -40096,7 +40064,7 @@ function _createPlanes( lodMax ) { } - return { lodPlanes, sizeLods, sigmas }; + return { lodMeshes, sizeLods, sigmas }; } @@ -40117,6 +40085,143 @@ function _setViewport( target, x, y, width, height ) { } +function _getGGXShader( lodMax, width, height ) { + + const shaderMaterial = new ShaderMaterial( { + + name: 'PMREMGGXConvolution', + + defines: { + 'GGX_SAMPLES': GGX_SAMPLES, + 'CUBEUV_TEXEL_WIDTH': 1.0 / width, + 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, + 'CUBEUV_MAX_MIP': `${lodMax}.0`, + }, + + uniforms: { + 'envMap': { value: null }, + 'roughness': { value: 0.0 }, + 'mipInt': { value: 0 } + }, + + vertexShader: _getCommonVertexShader(), + + fragmentShader: /* glsl */` + + precision highp float; + precision highp int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform float roughness; + uniform float mipInt; + + #define ENVMAP_TYPE_CUBE_UV + #include + + #define PI 3.14159265359 + + // Van der Corput radical inverse + float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 + } + + // Hammersley sequence + vec2 hammersley(uint i, uint N) { + return vec2(float(i) / float(N), radicalInverse_VdC(i)); + } + + // GGX VNDF importance sampling (Eric Heitz 2018) + // "Sampling the GGX Distribution of Visible Normals" + // https://jcgt.org/published/0007/04/01/ + vec3 importanceSampleGGX_VNDF(vec2 Xi, vec3 V, float roughness) { + float alpha = roughness * roughness; + + // Section 4.1: Orthonormal basis + vec3 T1 = vec3(1.0, 0.0, 0.0); + vec3 T2 = cross(V, T1); + + // Section 4.2: Parameterization of projected area + float r = sqrt(Xi.x); + float phi = 2.0 * PI * Xi.y; + float t1 = r * cos(phi); + float t2 = r * sin(phi); + float s = 0.5 * (1.0 + V.z); + t2 = (1.0 - s) * sqrt(1.0 - t1 * t1) + s * t2; + + // Section 4.3: Reprojection onto hemisphere + vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0, 1.0 - t1 * t1 - t2 * t2)) * V; + + // Section 3.4: Transform back to ellipsoid configuration + return normalize(vec3(alpha * Nh.x, alpha * Nh.y, max(0.0, Nh.z))); + } + + void main() { + vec3 N = normalize(vOutputDirection); + vec3 V = N; // Assume view direction equals normal for pre-filtering + + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + // For very low roughness, just sample the environment directly + if (roughness < 0.001) { + gl_FragColor = vec4(bilinearCubeUV(envMap, N, mipInt), 1.0); + return; + } + + // Tangent space basis for VNDF sampling + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + for(uint i = 0u; i < uint(GGX_SAMPLES); i++) { + vec2 Xi = hammersley(i, uint(GGX_SAMPLES)); + + // For PMREM, V = N, so in tangent space V is always (0, 0, 1) + vec3 H_tangent = importanceSampleGGX_VNDF(Xi, vec3(0.0, 0.0, 1.0), roughness); + + // Transform H back to world space + vec3 H = normalize(tangent * H_tangent.x + bitangent * H_tangent.y + N * H_tangent.z); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + + if(NdotL > 0.0) { + // Sample environment at fixed mip level + // VNDF importance sampling handles the distribution filtering + vec3 sampleColor = bilinearCubeUV(envMap, L, mipInt); + + // Weight by NdotL for the split-sum approximation + // VNDF PDF naturally accounts for the visible microfacet distribution + prefilteredColor += sampleColor * NdotL; + totalWeight += NdotL; + } + } + + if (totalWeight > 0.0) { + prefilteredColor = prefilteredColor / totalWeight; + } + + gl_FragColor = vec4(prefilteredColor, 1.0); + } + `, + + blending: NoBlending, + depthTest: false, + depthWrite: false + + } ); + + return shaderMaterial; + +} + function _getBlurShader( lodMax, width, height ) { const weights = new Float32Array( MAX_SAMPLES ); @@ -40357,13 +40462,576 @@ function _getCommonVertexShader() { } -function WebGLCubeUVMaps( renderer ) { +const fov = -90; // negative fov is not an error +const aspect = 1; + +/** + * A special type of camera that is positioned in 3D space to render its surroundings into a + * cube render target. The render target can then be used as an environment map for rendering + * realtime reflections in your scene. + * + * ```js + * // Create cube render target + * const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } ); + * + * // Create cube camera + * const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget ); + * scene.add( cubeCamera ); + * + * // Create car + * const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } ); + * const car = new THREE.Mesh( carGeometry, chromeMaterial ); + * scene.add( car ); + * + * // Update the render target cube + * car.visible = false; + * cubeCamera.position.copy( car.position ); + * cubeCamera.update( renderer, scene ); + * + * // Render the scene + * car.visible = true; + * renderer.render( scene, camera ); + * ``` + * + * @augments Object3D + */ +class CubeCamera extends Object3D { + + /** + * Constructs a new cube camera. + * + * @param {number} near - The camera's near plane. + * @param {number} far - The camera's far plane. + * @param {WebGLCubeRenderTarget} renderTarget - The cube render target. + */ + constructor( near, far, renderTarget ) { + + super(); + + this.type = 'CubeCamera'; + + /** + * A reference to the cube render target. + * + * @type {WebGLCubeRenderTarget} + */ + this.renderTarget = renderTarget; + + /** + * The current active coordinate system. + * + * @type {?(WebGLCoordinateSystem|WebGPUCoordinateSystem)} + * @default null + */ + this.coordinateSystem = null; + + /** + * The current active mipmap level + * + * @type {number} + * @default 0 + */ + this.activeMipmapLevel = 0; + + const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); + cameraPX.layers = this.layers; + this.add( cameraPX ); + + const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); + cameraNX.layers = this.layers; + this.add( cameraNX ); + + const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); + cameraPY.layers = this.layers; + this.add( cameraPY ); + + const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); + cameraNY.layers = this.layers; + this.add( cameraNY ); + + const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraPZ.layers = this.layers; + this.add( cameraPZ ); + + const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraNZ.layers = this.layers; + this.add( cameraNZ ); + + } + + /** + * Must be called when the coordinate system of the cube camera is changed. + */ + updateCoordinateSystem() { + + const coordinateSystem = this.coordinateSystem; + + const cameras = this.children.concat(); + + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; + + for ( const camera of cameras ) this.remove( camera ); + + if ( coordinateSystem === WebGLCoordinateSystem ) { + + cameraPX.up.set( 0, 1, 0 ); + cameraPX.lookAt( 1, 0, 0 ); + + cameraNX.up.set( 0, 1, 0 ); + cameraNX.lookAt( -1, 0, 0 ); + + cameraPY.up.set( 0, 0, -1 ); + cameraPY.lookAt( 0, 1, 0 ); + + cameraNY.up.set( 0, 0, 1 ); + cameraNY.lookAt( 0, -1, 0 ); + + cameraPZ.up.set( 0, 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); + + cameraNZ.up.set( 0, 1, 0 ); + cameraNZ.lookAt( 0, 0, -1 ); + + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { + + cameraPX.up.set( 0, -1, 0 ); + cameraPX.lookAt( -1, 0, 0 ); + + cameraNX.up.set( 0, -1, 0 ); + cameraNX.lookAt( 1, 0, 0 ); + + cameraPY.up.set( 0, 0, 1 ); + cameraPY.lookAt( 0, 1, 0 ); + + cameraNY.up.set( 0, 0, -1 ); + cameraNY.lookAt( 0, -1, 0 ); + + cameraPZ.up.set( 0, -1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); + + cameraNZ.up.set( 0, -1, 0 ); + cameraNZ.lookAt( 0, 0, -1 ); + + } else { + + throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); + + } + + for ( const camera of cameras ) { + + this.add( camera ); + + camera.updateMatrixWorld(); + + } + + } + + /** + * Calling this method will render the given scene with the given renderer + * into the cube render target of the camera. + * + * @param {(Renderer|WebGLRenderer)} renderer - The renderer. + * @param {Scene} scene - The scene to render. + */ + update( renderer, scene ) { + + if ( this.parent === null ) this.updateMatrixWorld(); + + const { renderTarget, activeMipmapLevel } = this; + + if ( this.coordinateSystem !== renderer.coordinateSystem ) { + + this.coordinateSystem = renderer.coordinateSystem; + + this.updateCoordinateSystem(); + + } + + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentActiveCubeFace = renderer.getActiveCubeFace(); + const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); + + const currentXrEnabled = renderer.xr.enabled; + + renderer.xr.enabled = false; + + const generateMipmaps = renderTarget.texture.generateMipmaps; + + renderTarget.texture.generateMipmaps = false; + + // https://github.com/mrdoob/three.js/issues/31413#issuecomment-3095966812 + + let reversedDepthBuffer = false; + + if ( renderer.isWebGLRenderer === true ) { + + reversedDepthBuffer = renderer.state.buffers.depth.getReversed(); + + } else { + + reversedDepthBuffer = renderer.reversedDepthBuffer; + + } + + renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); + if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth(); + renderer.render( scene, cameraPX ); + + renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); + if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth(); + renderer.render( scene, cameraNX ); + + renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); + if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth(); + renderer.render( scene, cameraPY ); + + renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); + if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth(); + renderer.render( scene, cameraNY ); + + renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); + if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth(); + renderer.render( scene, cameraPZ ); + + // mipmaps are generated during the last call of render() + // at this point, all sides of the cube render target are defined + + renderTarget.texture.generateMipmaps = generateMipmaps; + + renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); + if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth(); + renderer.render( scene, cameraNZ ); + + renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); + + renderer.xr.enabled = currentXrEnabled; + + renderTarget.texture.needsPMREMUpdate = true; + + } + +} + +/** + * Creates a cube texture made up of six images. + * + * ```js + * const loader = new THREE.CubeTextureLoader(); + * loader.setPath( 'textures/cube/pisa/' ); + * + * const textureCube = loader.load( [ + * 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' + * ] ); + * + * const material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } ); + * ``` + * + * @augments Texture + */ +class CubeTexture extends Texture { + + /** + * Constructs a new cube texture. + * + * @param {Array} [images=[]] - An array holding a image for each side of a cube. + * @param {number} [mapping=CubeReflectionMapping] - The texture mapping. + * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value. + * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value. + * @param {number} [magFilter=LinearFilter] - The mag filter value. + * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value. + * @param {number} [format=RGBAFormat] - The texture format. + * @param {number} [type=UnsignedByteType] - The texture type. + * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value. + * @param {string} [colorSpace=NoColorSpace] - The color space value. + */ + constructor( images = [], mapping = CubeReflectionMapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { + + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isCubeTexture = true; + + /** + * If set to `true`, the texture is flipped along the vertical axis when + * uploaded to the GPU. + * + * Overwritten and set to `false` by default. + * + * @type {boolean} + * @default false + */ + this.flipY = false; + + } + + /** + * Alias for {@link CubeTexture#image}. + * + * @type {Array} + */ + get images() { + + return this.image; + + } + + set images( value ) { + + this.image = value; + + } + +} + +/** + * A cube render target used in context of {@link WebGLRenderer}. + * + * @augments WebGLRenderTarget + */ +class WebGLCubeRenderTarget extends WebGLRenderTarget { + + /** + * Constructs a new cube render target. + * + * @param {number} [size=1] - The size of the render target. + * @param {RenderTarget~Options} [options] - The configuration object. + */ + constructor( size = 1, options = {} ) { + + super( size, size, options ); + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isWebGLCubeRenderTarget = true; + + const image = { width: size, height: size, depth: 1 }; + const images = [ image, image, image, image, image, image ]; + + /** + * Overwritten with a different texture type. + * + * @type {DataArrayTexture} + */ + this.texture = new CubeTexture( images ); + this._setTextureOptions( options ); + + // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) + // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, + // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. + + // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped + // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture + // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). + + this.texture.isRenderTargetTexture = true; + + } + + /** + * Converts the given equirectangular texture to a cube map. + * + * @param {WebGLRenderer} renderer - The renderer. + * @param {Texture} texture - The equirectangular texture. + * @return {WebGLCubeRenderTarget} A reference to this cube render target. + */ + fromEquirectangularTexture( renderer, texture ) { + + this.texture.type = texture.type; + this.texture.colorSpace = texture.colorSpace; + + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; + + const shader = { + + uniforms: { + tEquirect: { value: null }, + }, + + vertexShader: /* glsl */` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `, + + fragmentShader: /* glsl */` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + ` + }; + + const geometry = new BoxGeometry( 5, 5, 5 ); + + const material = new ShaderMaterial( { + + name: 'CubemapFromEquirect', + + uniforms: cloneUniforms( shader.uniforms ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide, + blending: NoBlending + + } ); + + material.uniforms.tEquirect.value = texture; + + const mesh = new Mesh( geometry, material ); + + const currentMinFilter = texture.minFilter; + + // Avoid blurred poles + if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; + + const camera = new CubeCamera( 1, 10, this ); + camera.update( renderer, mesh ); + + texture.minFilter = currentMinFilter; + + mesh.geometry.dispose(); + mesh.material.dispose(); + + return this; + + } + + /** + * Clears this cube render target. + * + * @param {WebGLRenderer} renderer - The renderer. + * @param {boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + */ + clear( renderer, color = true, depth = true, stencil = true ) { + + const currentRenderTarget = renderer.getRenderTarget(); + + for ( let i = 0; i < 6; i ++ ) { + + renderer.setRenderTarget( this, i ); + + renderer.clear( color, depth, stencil ); + + } + + renderer.setRenderTarget( currentRenderTarget ); + + } + +} + +function WebGLEnvironments( renderer ) { - let cubeUVmaps = new WeakMap(); + let cubeMaps = new WeakMap(); + let pmremMaps = new WeakMap(); let pmremGenerator = null; - function get( texture ) { + function get( texture, usePMREM = false ) { + + if ( texture === null || texture === undefined ) return null; + + if ( usePMREM ) { + + return getPMREM( texture ); + + } + + return getCube( texture ); + + } + + function getCube( texture ) { + + if ( texture && texture.isTexture ) { + + const mapping = texture.mapping; + + if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { + + if ( cubeMaps.has( texture ) ) { + + const cubemap = cubeMaps.get( texture ).texture; + return mapTextureMapping( cubemap, texture.mapping ); + + } else { + + const image = texture.image; + + if ( image && image.height > 0 ) { + + const renderTarget = new WebGLCubeRenderTarget( image.height ); + renderTarget.fromEquirectangularTexture( renderer, texture ); + cubeMaps.set( texture, renderTarget ); + + texture.addEventListener( 'dispose', onCubemapDispose ); + + return mapTextureMapping( renderTarget.texture, texture.mapping ); + + } else { + + // image not yet ready. try the conversion next frame + + return null; + + } + + } + + } + + } + + return texture; + + } + + function getPMREM( texture ) { if ( texture && texture.isTexture ) { @@ -40376,7 +41044,7 @@ function WebGLCubeUVMaps( renderer ) { if ( isEquirectMap || isCubeMap ) { - let renderTarget = cubeUVmaps.get( texture ); + let renderTarget = pmremMaps.get( texture ); const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0; @@ -40387,7 +41055,7 @@ function WebGLCubeUVMaps( renderer ) { renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); renderTarget.texture.pmremVersion = texture.pmremVersion; - cubeUVmaps.set( texture, renderTarget ); + pmremMaps.set( texture, renderTarget ); return renderTarget.texture; @@ -40408,9 +41076,9 @@ function WebGLCubeUVMaps( renderer ) { renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); renderTarget.texture.pmremVersion = texture.pmremVersion; - cubeUVmaps.set( texture, renderTarget ); + pmremMaps.set( texture, renderTarget ); - texture.addEventListener( 'dispose', onTextureDispose ); + texture.addEventListener( 'dispose', onPMREMDispose ); return renderTarget.texture; @@ -40434,6 +41102,22 @@ function WebGLCubeUVMaps( renderer ) { } + function mapTextureMapping( texture, mapping ) { + + if ( mapping === EquirectangularReflectionMapping ) { + + texture.mapping = CubeReflectionMapping; + + } else if ( mapping === EquirectangularRefractionMapping ) { + + texture.mapping = CubeRefractionMapping; + + } + + return texture; + + } + function isCubeTextureComplete( image ) { let count = 0; @@ -40447,21 +41131,37 @@ function WebGLCubeUVMaps( renderer ) { return count === length; + } + + function onCubemapDispose( event ) { + + const texture = event.target; + + texture.removeEventListener( 'dispose', onCubemapDispose ); + + const cubemap = cubeMaps.get( texture ); + + if ( cubemap !== undefined ) { + + cubeMaps.delete( texture ); + cubemap.dispose(); + + } } - function onTextureDispose( event ) { + function onPMREMDispose( event ) { const texture = event.target; - texture.removeEventListener( 'dispose', onTextureDispose ); + texture.removeEventListener( 'dispose', onPMREMDispose ); - const cubemapUV = cubeUVmaps.get( texture ); + const pmrem = pmremMaps.get( texture ); - if ( cubemapUV !== undefined ) { + if ( pmrem !== undefined ) { - cubeUVmaps.delete( texture ); - cubemapUV.dispose(); + pmremMaps.delete( texture ); + pmrem.dispose(); } @@ -40469,7 +41169,8 @@ function WebGLCubeUVMaps( renderer ) { function dispose() { - cubeUVmaps = new WeakMap(); + cubeMaps = new WeakMap(); + pmremMaps = new WeakMap(); if ( pmremGenerator !== null ) { @@ -40499,30 +41200,7 @@ function WebGLExtensions( gl ) { } - let extension; - - switch ( name ) { - - case 'WEBGL_depth_texture': - extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); - break; - - case 'EXT_texture_filter_anisotropic': - extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); - break; - - case 'WEBGL_compressed_texture_s3tc': - extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); - break; - - case 'WEBGL_compressed_texture_pvrtc': - extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); - break; - - default: - extension = gl.getExtension( name ); - - } + const extension = gl.getExtension( name ); extensions[ name ] = extension; @@ -40555,7 +41233,7 @@ function WebGLExtensions( gl ) { if ( extension === null ) { - warnOnce( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); + warnOnce( 'WebGLRenderer: ' + name + ' extension not supported.' ); } @@ -40651,6 +41329,12 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { const geometryPosition = geometry.attributes.position; let version = 0; + if ( geometryPosition === undefined ) { + + return; + + } + if ( geometryIndex !== null ) { const array = geometryIndex.array; @@ -40666,7 +41350,7 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } - } else if ( geometryPosition !== undefined ) { + } else { const array = geometryPosition.array; version = geometryPosition.version; @@ -40681,13 +41365,11 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } - } else { - - return; - } - const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + // check whether a 32 bit or 16 bit buffer is required to store the indices + // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + const attribute = new ( geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); attribute.version = version; // Updating index buffer in VAO now. See WebGLBindingStates @@ -40885,7 +41567,7 @@ function WebGLInfo( gl ) { break; default: - console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); + error( 'WebGLInfo: Unknown draw mode:', mode ); break; } @@ -41203,7 +41885,7 @@ function WebGLMorphtargets( gl, capabilities, textures ) { } -function WebGLObjects( gl, geometries, attributes, info ) { +function WebGLObjects( gl, geometries, attributes, bindingStates, info ) { let updateMap = new WeakMap(); @@ -41278,6 +41960,8 @@ function WebGLObjects( gl, geometries, attributes, info ) { instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); + bindingStates.releaseStatesOfObject( instancedMesh ); + attributes.remove( instancedMesh.instanceMatrix ); if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); @@ -41293,6 +41977,291 @@ function WebGLObjects( gl, geometries, attributes, info ) { } +/** + * This class works just like {@link ShaderMaterial}, except that definitions + * of built-in uniforms and attributes are not automatically prepended to the + * GLSL shader code. + * + * `RawShaderMaterial` can only be used with {@link WebGLRenderer}. + * + * @augments ShaderMaterial + */ +class RawShaderMaterial extends ShaderMaterial { + + /** + * Constructs a new raw shader material. + * + * @param {Object} [parameters] - An object with one or more properties + * defining the material's appearance. Any property of the material + * (including any property from inherited materials) can be passed + * in here. Color values can be passed any type of value accepted + * by {@link Color#set}. + */ + constructor( parameters ) { + + super( parameters ); + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isRawShaderMaterial = true; + + this.type = 'RawShaderMaterial'; + + } + +} + +const toneMappingMap = { + [ LinearToneMapping ]: 'LINEAR_TONE_MAPPING', + [ ReinhardToneMapping ]: 'REINHARD_TONE_MAPPING', + [ CineonToneMapping ]: 'CINEON_TONE_MAPPING', + [ ACESFilmicToneMapping ]: 'ACES_FILMIC_TONE_MAPPING', + [ AgXToneMapping ]: 'AGX_TONE_MAPPING', + [ NeutralToneMapping ]: 'NEUTRAL_TONE_MAPPING', + [ CustomToneMapping ]: 'CUSTOM_TONE_MAPPING' +}; + +function WebGLOutput( type, width, height, depth, stencil ) { + + // render targets for scene and post-processing + const targetA = new WebGLRenderTarget( width, height, { + type: type, + depthBuffer: depth, + stencilBuffer: stencil + } ); + + const targetB = new WebGLRenderTarget( width, height, { + type: HalfFloatType, + depthBuffer: false, + stencilBuffer: false + } ); + + // create fullscreen triangle geometry + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( [ -1, 3, 0, -1, -1, 0, 3, -1, 0 ], 3 ) ); + geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); + + // create output material with tone mapping support + const material = new RawShaderMaterial( { + uniforms: { + tDiffuse: { value: null } + }, + vertexShader: /* glsl */` + precision highp float; + + uniform mat4 modelViewMatrix; + uniform mat4 projectionMatrix; + + attribute vec3 position; + attribute vec2 uv; + + varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, + fragmentShader: /* glsl */` + precision highp float; + + uniform sampler2D tDiffuse; + + varying vec2 vUv; + + #include + #include + + void main() { + gl_FragColor = texture2D( tDiffuse, vUv ); + + #ifdef LINEAR_TONE_MAPPING + gl_FragColor.rgb = LinearToneMapping( gl_FragColor.rgb ); + #elif defined( REINHARD_TONE_MAPPING ) + gl_FragColor.rgb = ReinhardToneMapping( gl_FragColor.rgb ); + #elif defined( CINEON_TONE_MAPPING ) + gl_FragColor.rgb = CineonToneMapping( gl_FragColor.rgb ); + #elif defined( ACES_FILMIC_TONE_MAPPING ) + gl_FragColor.rgb = ACESFilmicToneMapping( gl_FragColor.rgb ); + #elif defined( AGX_TONE_MAPPING ) + gl_FragColor.rgb = AgXToneMapping( gl_FragColor.rgb ); + #elif defined( NEUTRAL_TONE_MAPPING ) + gl_FragColor.rgb = NeutralToneMapping( gl_FragColor.rgb ); + #elif defined( CUSTOM_TONE_MAPPING ) + gl_FragColor.rgb = CustomToneMapping( gl_FragColor.rgb ); + #endif + + #ifdef SRGB_TRANSFER + gl_FragColor = sRGBTransferOETF( gl_FragColor ); + #endif + }`, + depthTest: false, + depthWrite: false + } ); + + const mesh = new Mesh( geometry, material ); + const camera = new OrthographicCamera( -1, 1, 1, -1, 0, 1 ); + + let _outputColorSpace = null; + let _outputToneMapping = null; + let _isCompositing = false; + let _savedToneMapping; + let _savedRenderTarget = null; + let _effects = []; + let _hasRenderPass = false; + + this.setSize = function ( width, height ) { + + targetA.setSize( width, height ); + targetB.setSize( width, height ); + + for ( let i = 0; i < _effects.length; i ++ ) { + + const effect = _effects[ i ]; + if ( effect.setSize ) effect.setSize( width, height ); + + } + + }; + + this.setEffects = function ( effects ) { + + _effects = effects; + _hasRenderPass = _effects.length > 0 && _effects[ 0 ].isRenderPass === true; + + const width = targetA.width; + const height = targetA.height; + + for ( let i = 0; i < _effects.length; i ++ ) { + + const effect = _effects[ i ]; + if ( effect.setSize ) effect.setSize( width, height ); + + } + + }; + + this.begin = function ( renderer, renderTarget ) { + + // Don't begin during compositing phase (post-processing effects call render()) + if ( _isCompositing ) return false; + + if ( renderer.toneMapping === NoToneMapping && _effects.length === 0 ) return false; + + _savedRenderTarget = renderTarget; + + // resize internal buffers to match render target (e.g. XR resolution) + if ( renderTarget !== null ) { + + const width = renderTarget.width; + const height = renderTarget.height; + + if ( targetA.width !== width || targetA.height !== height ) { + + this.setSize( width, height ); + + } + + } + + // if first effect is a RenderPass, it will set its own render target + if ( _hasRenderPass === false ) { + + renderer.setRenderTarget( targetA ); + + } + + // disable tone mapping during render - it will be applied in end() + _savedToneMapping = renderer.toneMapping; + renderer.toneMapping = NoToneMapping; + + return true; + + }; + + this.hasRenderPass = function () { + + return _hasRenderPass; + + }; + + this.end = function ( renderer, deltaTime ) { + + // restore tone mapping + renderer.toneMapping = _savedToneMapping; + + _isCompositing = true; + + // run post-processing effects + let readBuffer = targetA; + let writeBuffer = targetB; + + for ( let i = 0; i < _effects.length; i ++ ) { + + const effect = _effects[ i ]; + + if ( effect.enabled === false ) continue; + + effect.render( renderer, writeBuffer, readBuffer, deltaTime ); + + if ( effect.needsSwap !== false ) { + + const temp = readBuffer; + readBuffer = writeBuffer; + writeBuffer = temp; + + } + + } + + // update output material defines if settings changed + if ( _outputColorSpace !== renderer.outputColorSpace || _outputToneMapping !== renderer.toneMapping ) { + + _outputColorSpace = renderer.outputColorSpace; + _outputToneMapping = renderer.toneMapping; + + material.defines = {}; + + if ( ColorManagement.getTransfer( _outputColorSpace ) === SRGBTransfer ) material.defines.SRGB_TRANSFER = ''; + + const toneMapping = toneMappingMap[ _outputToneMapping ]; + if ( toneMapping ) material.defines[ toneMapping ] = ''; + + material.needsUpdate = true; + + } + + // final output to canvas (or XR render target) + material.uniforms.tDiffuse.value = readBuffer.texture; + renderer.setRenderTarget( _savedRenderTarget ); + renderer.render( mesh, camera ); + + _savedRenderTarget = null; + _isCompositing = false; + + }; + + this.isCompositing = function () { + + return _isCompositing; + + }; + + this.dispose = function () { + + targetA.dispose(); + targetB.dispose(); + geometry.dispose(); + material.dispose(); + + }; + +} + /** * Creates a three-dimensional texture from raw data, with parameters to * divide it into width, height, and depth. @@ -42068,7 +43037,7 @@ function setValueT1( gl, v, textures ) { if ( this.type === gl.SAMPLER_2D_SHADOW ) { - emptyShadowTexture.compareFunction = LessEqualCompare; // #28670 + emptyShadowTexture.compareFunction = textures.isReversedDepthBuffer() ? GreaterEqualCompare : LessEqualCompare; emptyTexture2D = emptyShadowTexture; } else { @@ -42318,9 +43287,21 @@ function setValueT1Array( gl, v, textures ) { } + let emptyTexture2D; + + if ( this.type === gl.SAMPLER_2D_SHADOW ) { + + emptyTexture2D = emptyShadowTexture; + + } else { + + emptyTexture2D = emptyTexture; + + } + for ( let i = 0; i !== n; ++ i ) { - textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); + textures.setTexture2D( v[ i ] || emptyTexture2D, units[ i ] ); } @@ -42606,6 +43587,31 @@ class WebGLUniforms { } + // Sort uniforms to prioritize shadow samplers first (for optimal texture unit allocation) + + const shadowSamplers = []; + const otherUniforms = []; + + for ( const u of this.seq ) { + + if ( u.type === gl.SAMPLER_2D_SHADOW || u.type === gl.SAMPLER_CUBE_SHADOW || u.type === gl.SAMPLER_2D_ARRAY_SHADOW ) { + + shadowSamplers.push( u ); + + } else { + + otherUniforms.push( u ); + + } + + } + + if ( shadowSamplers.length > 0 ) { + + this.seq = shadowSamplers.concat( otherUniforms ); + + } + } setValue( gl, name, value, textures ) { @@ -42711,7 +43717,7 @@ function getEncodingComponents( colorSpace ) { return [ encodingMatrix, 'sRGBTransferOETF' ]; default: - console.warn( 'THREE.WebGLProgram: Unsupported color space: ', colorSpace ); + warn( 'WebGLProgram: Unsupported color space: ', colorSpace ); return [ encodingMatrix, 'LinearTransferOETF' ]; } @@ -42731,7 +43737,7 @@ function getShaderErrors( gl, shader, type ) { if ( errorMatches ) { // --enable-privileged-webgl-extension - // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); + // log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); const errorLine = parseInt( errorMatches[ 1 ] ); return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); @@ -42760,43 +43766,24 @@ function getTexelEncodingFunction( functionName, colorSpace ) { } -function getToneMappingFunction( functionName, toneMapping ) { - - let toneMappingName; - - switch ( toneMapping ) { - - case LinearToneMapping: - toneMappingName = 'Linear'; - break; - - case ReinhardToneMapping: - toneMappingName = 'Reinhard'; - break; - - case CineonToneMapping: - toneMappingName = 'Cineon'; - break; - - case ACESFilmicToneMapping: - toneMappingName = 'ACESFilmic'; - break; +const toneMappingFunctions = { + [ LinearToneMapping ]: 'Linear', + [ ReinhardToneMapping ]: 'Reinhard', + [ CineonToneMapping ]: 'Cineon', + [ ACESFilmicToneMapping ]: 'ACESFilmic', + [ AgXToneMapping ]: 'AgX', + [ NeutralToneMapping ]: 'Neutral', + [ CustomToneMapping ]: 'Custom' +}; - case AgXToneMapping: - toneMappingName = 'AgX'; - break; +function getToneMappingFunction( functionName, toneMapping ) { - case NeutralToneMapping: - toneMappingName = 'Neutral'; - break; + const toneMappingName = toneMappingFunctions[ toneMapping ]; - case CustomToneMapping: - toneMappingName = 'Custom'; - break; + if ( toneMappingName === undefined ) { - default: - console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); - toneMappingName = 'Linear'; + warn( 'WebGLProgram: Unsupported toneMapping:', toneMapping ); + return 'vec3 ' + functionName + '( vec3 color ) { return LinearToneMapping( color ); }'; } @@ -42873,7 +43860,7 @@ function fetchAttributeLocations( gl, program ) { if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3; if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4; - // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); + // log( 'WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); attributes[ name ] = { type: info.type, @@ -42943,7 +43930,7 @@ function includeReplacer( match, include ) { if ( newInclude !== undefined ) { string = ShaderChunk[ newInclude ]; - console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); + warn( 'WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); } else { @@ -43024,99 +44011,54 @@ function generatePrecision( parameters ) { } -function generateShadowMapTypeDefine( parameters ) { - - let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; - - if ( parameters.shadowMapType === PCFShadowMap ) { - - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; - - } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { - - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; - - } else if ( parameters.shadowMapType === VSMShadowMap ) { - - shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; +const shadowMapTypeDefines = { + [ PCFShadowMap ]: 'SHADOWMAP_TYPE_PCF', + [ VSMShadowMap ]: 'SHADOWMAP_TYPE_VSM' +}; - } +function generateShadowMapTypeDefine( parameters ) { - return shadowMapTypeDefine; + return shadowMapTypeDefines[ parameters.shadowMapType ] || 'SHADOWMAP_TYPE_BASIC'; } -function generateEnvMapTypeDefine( parameters ) { - - let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - - if ( parameters.envMap ) { - - switch ( parameters.envMapMode ) { - - case CubeReflectionMapping: - case CubeRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - break; - - case CubeUVReflectionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; - break; +const envMapTypeDefines = { + [ CubeReflectionMapping ]: 'ENVMAP_TYPE_CUBE', + [ CubeRefractionMapping ]: 'ENVMAP_TYPE_CUBE', + [ CubeUVReflectionMapping ]: 'ENVMAP_TYPE_CUBE_UV' +}; - } +function generateEnvMapTypeDefine( parameters ) { - } + if ( parameters.envMap === false ) return 'ENVMAP_TYPE_CUBE'; - return envMapTypeDefine; + return envMapTypeDefines[ parameters.envMapMode ] || 'ENVMAP_TYPE_CUBE'; } -function generateEnvMapModeDefine( parameters ) { - - let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; - - if ( parameters.envMap ) { - - switch ( parameters.envMapMode ) { - - case CubeRefractionMapping: - - envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; - break; +const envMapModeDefines = { + [ CubeRefractionMapping ]: 'ENVMAP_MODE_REFRACTION' +}; - } +function generateEnvMapModeDefine( parameters ) { - } + if ( parameters.envMap === false ) return 'ENVMAP_MODE_REFLECTION'; - return envMapModeDefine; + return envMapModeDefines[ parameters.envMapMode ] || 'ENVMAP_MODE_REFLECTION'; } -function generateEnvMapBlendingDefine( parameters ) { - - let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; - - if ( parameters.envMap ) { - - switch ( parameters.combine ) { - - case MultiplyOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; - break; - - case MixOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; - break; - - case AddOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; - break; +const envMapBlendingDefines = { + [ MultiplyOperation ]: 'ENVMAP_BLENDING_MULTIPLY', + [ MixOperation ]: 'ENVMAP_BLENDING_MIX', + [ AddOperation ]: 'ENVMAP_BLENDING_ADD' +}; - } +function generateEnvMapBlendingDefine( parameters ) { - } + if ( parameters.envMap === false ) return 'ENVMAP_BLENDING_NONE'; - return envMapBlendingDefine; + return envMapBlendingDefines[ parameters.combine ] || 'ENVMAP_BLENDING_NONE'; } @@ -43139,7 +44081,7 @@ function generateCubeUVSize( parameters ) { function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { // TODO Send this event to Three.js DevTools - // console.log( 'WebGLProgram', cacheKey ); + // log( 'WebGLProgram', cacheKey ); const gl = renderer.getContext(); @@ -43459,8 +44401,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', - parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '', - parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', + parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', + parameters.vertexAlphas || parameters.batchingColor ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUv1s ? '#define USE_UV1' : '', parameters.vertexUv2s ? '#define USE_UV2' : '', parameters.vertexUv3s ? '#define USE_UV3' : '', @@ -43555,8 +44497,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { const vertexGlsl = versionString + prefixVertex + vertexShader; const fragmentGlsl = versionString + prefixFragment + fragmentShader; - // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); + // log( '*VERTEX*', vertexGlsl ); + // log( '*FRAGMENT*', fragmentGlsl ); const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); @@ -43610,7 +44552,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); - console.error( + error( 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + 'Material Name: ' + self.name + '\n' + @@ -43624,7 +44566,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { } else if ( programLog !== '' ) { - console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); + warn( 'WebGLProgram: Program Info Log:', programLog ); } else if ( vertexLog === '' || fragmentLog === '' ) { @@ -43874,21 +44816,21 @@ class WebGLShaderStage { } -function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { +function WebGLPrograms( renderer, environments, extensions, capabilities, bindingStates, clipping ) { const _programLayers = new Layers(); const _customShaders = new WebGLShaderCache(); const _activeChannels = new Set(); const programs = []; + const programsMap = new Map(); const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; - const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; let precision = capabilities.precision; const shaderIDs = { MeshDepthMaterial: 'depth', - MeshDistanceMaterial: 'distanceRGBA', + MeshDistanceMaterial: 'distance', MeshNormalMaterial: 'normal', MeshBasicMaterial: 'basic', MeshLambertMaterial: 'lambert', @@ -43918,9 +44860,10 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const fog = scene.fog; const geometry = object.geometry; - const environment = material.isMeshStandardMaterial ? scene.environment : null; + const environment = ( material.isMeshStandardMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial ) ? scene.environment : null; - const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const usePMREM = material.isMeshStandardMaterial || ( material.isMeshLambertMaterial && ! material.envMap ) || ( material.isMeshPhongMaterial && ! material.envMap ); + const envMap = environments.get( material.envMap || environment, usePMREM ); const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null; const shaderID = shaderIDs[ material.type ]; @@ -43934,7 +44877,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities if ( precision !== material.precision ) { - console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); + warn( 'WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); } @@ -44066,7 +45009,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, - supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), alphaToCoverage: !! material.alphaToCoverage, @@ -44079,7 +45021,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities lightMap: HAS_LIGHTMAP, bumpMap: HAS_BUMPMAP, normalMap: HAS_NORMALMAP, - displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + displacementMap: HAS_DISPLACEMENTMAP, emissiveMap: HAS_EMISSIVEMAP, normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, @@ -44170,7 +45112,12 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities useFog: material.fog === true, fogExp2: ( !! fog && fog.isFogExp2 ), - flatShading: ( material.flatShading === true && material.wireframe === false ), + flatShading: material.wireframe === false && ( + material.flatShading === true || + ( geometry.attributes.normal === undefined && HAS_NORMALMAP === false && + ( material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.isMeshPhysicalMaterial ) + ) + ), sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, @@ -44339,52 +45286,50 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.disableAll(); - if ( parameters.supportsVertexTextures ) - _programLayers.enable( 0 ); if ( parameters.instancing ) - _programLayers.enable( 1 ); + _programLayers.enable( 0 ); if ( parameters.instancingColor ) - _programLayers.enable( 2 ); + _programLayers.enable( 1 ); if ( parameters.instancingMorph ) - _programLayers.enable( 3 ); + _programLayers.enable( 2 ); if ( parameters.matcap ) - _programLayers.enable( 4 ); + _programLayers.enable( 3 ); if ( parameters.envMap ) - _programLayers.enable( 5 ); + _programLayers.enable( 4 ); if ( parameters.normalMapObjectSpace ) - _programLayers.enable( 6 ); + _programLayers.enable( 5 ); if ( parameters.normalMapTangentSpace ) - _programLayers.enable( 7 ); + _programLayers.enable( 6 ); if ( parameters.clearcoat ) - _programLayers.enable( 8 ); + _programLayers.enable( 7 ); if ( parameters.iridescence ) - _programLayers.enable( 9 ); + _programLayers.enable( 8 ); if ( parameters.alphaTest ) - _programLayers.enable( 10 ); + _programLayers.enable( 9 ); if ( parameters.vertexColors ) - _programLayers.enable( 11 ); + _programLayers.enable( 10 ); if ( parameters.vertexAlphas ) - _programLayers.enable( 12 ); + _programLayers.enable( 11 ); if ( parameters.vertexUv1s ) - _programLayers.enable( 13 ); + _programLayers.enable( 12 ); if ( parameters.vertexUv2s ) - _programLayers.enable( 14 ); + _programLayers.enable( 13 ); if ( parameters.vertexUv3s ) - _programLayers.enable( 15 ); + _programLayers.enable( 14 ); if ( parameters.vertexTangents ) - _programLayers.enable( 16 ); + _programLayers.enable( 15 ); if ( parameters.anisotropy ) - _programLayers.enable( 17 ); + _programLayers.enable( 16 ); if ( parameters.alphaHash ) - _programLayers.enable( 18 ); + _programLayers.enable( 17 ); if ( parameters.batching ) - _programLayers.enable( 19 ); + _programLayers.enable( 18 ); if ( parameters.dispersion ) - _programLayers.enable( 20 ); + _programLayers.enable( 19 ); if ( parameters.batchingColor ) - _programLayers.enable( 21 ); + _programLayers.enable( 20 ); if ( parameters.gradientMap ) - _programLayers.enable( 22 ); + _programLayers.enable( 21 ); array.push( _programLayers.mask ); _programLayers.disableAll(); @@ -44460,29 +45405,19 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities function acquireProgram( parameters, cacheKey ) { - let program; + let program = programsMap.get( cacheKey ); - // Check if code has been already compiled - for ( let p = 0, pl = programs.length; p < pl; p ++ ) { + if ( program !== undefined ) { - const preexistingProgram = programs[ p ]; + ++ program.usedTimes; - if ( preexistingProgram.cacheKey === cacheKey ) { - - program = preexistingProgram; - ++ program.usedTimes; - - break; - - } - - } - - if ( program === undefined ) { + } else { program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); programs.push( program ); + programsMap.set( cacheKey, program ); + } return program; @@ -44498,6 +45433,9 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities programs[ i ] = programs[ programs.length - 1 ]; programs.pop(); + // Remove from map + programsMap.delete( program.cacheKey ); + // Free WebGL resources program.destroy(); @@ -44598,6 +45536,10 @@ function painterSortStable( a, b ) { return a.material.id - b.material.id; + } else if ( a.materialVariant !== b.materialVariant ) { + + return a.materialVariant - b.materialVariant; + } else if ( a.z !== b.z ) { return a.z - b.z; @@ -44652,6 +45594,15 @@ function WebGLRenderList() { } + function materialVariant( object ) { + + let variant = 0; + if ( object.isInstancedMesh ) variant += 2; + if ( object.isSkinnedMesh ) variant += 1; + return variant; + + } + function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { let renderItem = renderItems[ renderItemsIndex ]; @@ -44663,6 +45614,7 @@ function WebGLRenderList() { object: object, geometry: geometry, material: material, + materialVariant: materialVariant( object ), groupOrder: groupOrder, renderOrder: object.renderOrder, z: z, @@ -44677,6 +45629,7 @@ function WebGLRenderList() { renderItem.object = object; renderItem.geometry = geometry; renderItem.material = material; + renderItem.materialVariant = materialVariant( object ); renderItem.groupOrder = groupOrder; renderItem.renderOrder = object.renderOrder; renderItem.z = z; @@ -45055,7 +46008,23 @@ function WebGLLights( extensions ) { const intensity = light.intensity; const distance = light.distance; - const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; + let shadowMap = null; + + if ( light.shadow && light.shadow.map ) { + + if ( light.shadow.map.texture.format === RGFormat ) { + + // VSM uses color texture with blurred mean/std_dev + shadowMap = light.shadow.map.texture; + + } else { + + // Other types use depth texture + shadowMap = light.shadow.map.depthTexture || light.shadow.map.texture; + + } + + } if ( light.isAmbientLight ) { @@ -45493,6 +46462,7 @@ function WebGLRenderStates( extensions ) { * near and far plane. White is nearest, black is farthest. * * @augments Material + * @demo scenes/material-browser.html#MeshDepthMaterial */ class MeshDepthMaterial extends Material { @@ -45747,9 +46717,95 @@ class MeshDistanceMaterial extends Material { } +/** + * This class can be used to automatically save the depth information of a + * cube rendering into a cube texture with depth format. Used for PointLight shadows. + * + * @augments DepthTexture + */ +class CubeDepthTexture extends DepthTexture { + + /** + * Constructs a new cube depth texture. + * + * @param {number} size - The size (width and height) of each cube face. + * @param {number} [type=UnsignedIntType] - The texture type. + * @param {number} [mapping=CubeReflectionMapping] - The texture mapping. + * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value. + * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value. + * @param {number} [magFilter=NearestFilter] - The mag filter value. + * @param {number} [minFilter=NearestFilter] - The min filter value. + * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value. + * @param {number} [format=DepthFormat] - The texture format. + */ + constructor( size, type = UnsignedIntType, mapping = CubeReflectionMapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, format = DepthFormat ) { + + // Create 6 identical image descriptors for the cube faces + const image = { width: size, height: size, depth: 1 }; + const images = [ image, image, image, image, image, image ]; + + // Call DepthTexture constructor with width, height + super( size, size, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ); + + // Replace the single image with the array of 6 images + this.image = images; + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isCubeDepthTexture = true; + + /** + * Set to true for cube texture handling in WebGLTextures. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isCubeTexture = true; + + } + + /** + * Alias for {@link CubeDepthTexture#image}. + * + * @type {Array} + */ + get images() { + + return this.image; + + } + + set images( value ) { + + this.image = value; + + } + +} + const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; -const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; +const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ).rg;\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ).r;\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( max( 0.0, squared_mean - mean * mean ) );\n\tgl_FragColor = vec4( mean, std_dev, 0.0, 1.0 );\n}"; + +const _cubeDirections = [ + /*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( -1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), + /*@__PURE__*/ new Vector3( 0, -1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, -1 ) +]; + +const _cubeUps = [ + /*@__PURE__*/ new Vector3( 0, -1, 0 ), /*@__PURE__*/ new Vector3( 0, -1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), + /*@__PURE__*/ new Vector3( 0, 0, -1 ), /*@__PURE__*/ new Vector3( 0, -1, 0 ), /*@__PURE__*/ new Vector3( 0, -1, 0 ) +]; + +const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); +const _lookTarget$1 = /*@__PURE__*/ new Vector3(); function WebGLShadowMap( renderer, objects, capabilities ) { @@ -45760,7 +46816,7 @@ function WebGLShadowMap( renderer, objects, capabilities ) { _viewport = new Vector4(), - _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), + _depthMaterial = new MeshDepthMaterial(), _distanceMaterial = new MeshDistanceMaterial(), _materialCache = {}, @@ -45815,6 +46871,13 @@ function WebGLShadowMap( renderer, objects, capabilities ) { if ( lights.length === 0 ) return; + if ( this.type === PCFSoftShadowMap ) { + + warn( 'WebGLShadowMap: PCFSoftShadowMap has been deprecated. Using PCFShadowMap instead.' ); + this.type = PCFShadowMap; + + } + const currentRenderTarget = renderer.getRenderTarget(); const activeCubeFace = renderer.getActiveCubeFace(); const activeMipmapLevel = renderer.getActiveMipmapLevel(); @@ -45839,8 +46902,31 @@ function WebGLShadowMap( renderer, objects, capabilities ) { // check for shadow map type changes - const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); - const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); + const typeChanged = _previousType !== this.type; + + // When shadow map type changes, materials need recompilation because sampler types change + // (sampler2DShadow for PCF vs sampler2D for Basic) + if ( typeChanged ) { + + scene.traverse( function ( object ) { + + if ( object.material ) { + + if ( Array.isArray( object.material ) ) { + + object.material.forEach( mat => mat.needsUpdate = true ); + + } else { + + object.material.needsUpdate = true; + + } + + } + + } ); + + } // render depth map @@ -45851,7 +46937,7 @@ function WebGLShadowMap( renderer, objects, capabilities ) { if ( shadow === undefined ) { - console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); + warn( 'WebGLShadowMap:', light, 'has no shadow.' ); continue; } @@ -45886,42 +46972,154 @@ function WebGLShadowMap( renderer, objects, capabilities ) { } - if ( shadow.map === null || toVSM === true || fromVSM === true ) { + const reversedDepthBuffer = renderer.state.buffers.depth.getReversed(); + shadow.camera._reversedDepth = reversedDepthBuffer; - const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; + if ( shadow.map === null || typeChanged === true ) { if ( shadow.map !== null ) { + if ( shadow.map.depthTexture !== null ) { + + shadow.map.depthTexture.dispose(); + shadow.map.depthTexture = null; + + } + shadow.map.dispose(); } - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + '.shadowMap'; + if ( this.type === VSMShadowMap ) { + + if ( light.isPointLight ) { + + warn( 'WebGLShadowMap: VSM shadow maps are not supported for PointLights. Use PCF or BasicShadowMap instead.' ); + continue; + + } + + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, { + format: RGFormat, + type: HalfFloatType, + minFilter: LinearFilter, + magFilter: LinearFilter, + generateMipmaps: false + } ); + shadow.map.texture.name = light.name + '.shadowMap'; + + // Native depth texture for VSM - depth is captured here, then blurred into the color texture + shadow.map.depthTexture = new DepthTexture( _shadowMapSize.x, _shadowMapSize.y, FloatType ); + shadow.map.depthTexture.name = light.name + '.shadowMapDepth'; + shadow.map.depthTexture.format = DepthFormat; + shadow.map.depthTexture.compareFunction = null; // For regular sampling (not shadow comparison) + shadow.map.depthTexture.minFilter = NearestFilter; + shadow.map.depthTexture.magFilter = NearestFilter; + + } else { + + if ( light.isPointLight ) { + + shadow.map = new WebGLCubeRenderTarget( _shadowMapSize.x ); + shadow.map.depthTexture = new CubeDepthTexture( _shadowMapSize.x, UnsignedIntType ); + + } else { + + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); + shadow.map.depthTexture = new DepthTexture( _shadowMapSize.x, _shadowMapSize.y, UnsignedIntType ); + + } + + shadow.map.depthTexture.name = light.name + '.shadowMap'; + shadow.map.depthTexture.format = DepthFormat; + + if ( this.type === PCFShadowMap ) { + + shadow.map.depthTexture.compareFunction = reversedDepthBuffer ? GreaterEqualCompare : LessEqualCompare; + shadow.map.depthTexture.minFilter = LinearFilter; + shadow.map.depthTexture.magFilter = LinearFilter; + + } else { + + shadow.map.depthTexture.compareFunction = null; + shadow.map.depthTexture.minFilter = NearestFilter; + shadow.map.depthTexture.magFilter = NearestFilter; + + } + + } shadow.camera.updateProjectionMatrix(); } - renderer.setRenderTarget( shadow.map ); - renderer.clear(); + // For cube render targets (PointLights), render all 6 faces. Otherwise, render once. + const faceCount = shadow.map.isWebGLCubeRenderTarget ? 6 : 1; - const viewportCount = shadow.getViewportCount(); + for ( let face = 0; face < faceCount; face ++ ) { - for ( let vp = 0; vp < viewportCount; vp ++ ) { + // For cube render targets, render to each face separately + if ( shadow.map.isWebGLCubeRenderTarget ) { - const viewport = shadow.getViewport( vp ); + renderer.setRenderTarget( shadow.map, face ); + renderer.clear(); - _viewport.set( - _viewportSize.x * viewport.x, - _viewportSize.y * viewport.y, - _viewportSize.x * viewport.z, - _viewportSize.y * viewport.w - ); + } else { + + // For 2D render targets, use viewports + if ( face === 0 ) { + + renderer.setRenderTarget( shadow.map ); + renderer.clear(); + + } + + const viewport = shadow.getViewport( face ); + + _viewport.set( + _viewportSize.x * viewport.x, + _viewportSize.y * viewport.y, + _viewportSize.x * viewport.z, + _viewportSize.y * viewport.w + ); + + _state.viewport( _viewport ); + + } + + if ( light.isPointLight ) { + + const camera = shadow.camera; + const shadowMatrix = shadow.matrix; + + const far = light.distance || camera.far; + + if ( far !== camera.far ) { - _state.viewport( _viewport ); + camera.far = far; + camera.updateProjectionMatrix(); - shadow.updateMatrices( light, vp ); + } + + _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); + camera.position.copy( _lightPositionWorld$1 ); + + _lookTarget$1.copy( camera.position ); + _lookTarget$1.add( _cubeDirections[ face ] ); + camera.up.copy( _cubeUps[ face ] ); + camera.lookAt( _lookTarget$1 ); + camera.updateMatrixWorld(); + + shadowMatrix.makeTranslation( - _lightPositionWorld$1.x, - _lightPositionWorld$1.y, - _lightPositionWorld$1.z ); + + _projScreenMatrix$2.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + shadow._frustum.setFromProjectionMatrix( _projScreenMatrix$2, camera.coordinateSystem, camera.reversedDepth ); + + } else { + + shadow.updateMatrices( light ); + + } _frustum = shadow.getFrustum(); @@ -45965,13 +47163,16 @@ function WebGLShadowMap( renderer, objects, capabilities ) { if ( shadow.mapPass === null ) { - shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); + shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, { + format: RGFormat, + type: HalfFloatType + } ); } - // vertical pass + // vertical pass - read from native depth texture - shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; + shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.depthTexture; shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; shadowMaterialVertical.uniforms.radius.value = shadow.radius; renderer.setRenderTarget( shadow.mapPass ); @@ -46170,18 +47371,6 @@ function WebGLShadowMap( renderer, objects, capabilities ) { } -const reversedFuncs = { - [ NeverDepth ]: AlwaysDepth, - [ LessDepth ]: GreaterDepth, - [ EqualDepth ]: NotEqualDepth, - [ LessEqualDepth ]: GreaterEqualDepth, - - [ AlwaysDepth ]: NeverDepth, - [ GreaterDepth ]: LessDepth, - [ NotEqualDepth ]: EqualDepth, - [ GreaterEqualDepth ]: LessEqualDepth, -}; - function WebGLState( gl, extensions ) { function ColorBuffer() { @@ -46313,7 +47502,7 @@ function WebGLState( gl, extensions ) { setFunc: function ( depthFunc ) { - if ( currentReversed ) depthFunc = reversedFuncs[ depthFunc ]; + if ( currentReversed ) depthFunc = ReversedDepthFuncs[ depthFunc ]; if ( currentDepthFunc !== depthFunc ) { @@ -46381,6 +47570,8 @@ function WebGLState( gl, extensions ) { if ( currentDepthClear !== depth ) { + currentDepthClear = depth; + if ( currentReversed ) { depth = 1 - depth; @@ -46388,7 +47579,6 @@ function WebGLState( gl, extensions ) { } gl.clearDepth( depth ); - currentDepthClear = depth; } @@ -46839,7 +48029,7 @@ function WebGLState( gl, extensions ) { break; default: - console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + error( 'WebGLState: Invalid blending: ', blending ); break; } @@ -46857,15 +48047,15 @@ function WebGLState( gl, extensions ) { break; case SubtractiveBlending: - console.error( 'THREE.WebGLState: SubtractiveBlending requires material.premultipliedAlpha = true' ); + error( 'WebGLState: SubtractiveBlending requires material.premultipliedAlpha = true' ); break; case MultiplyBlending: - console.error( 'THREE.WebGLState: MultiplyBlending requires material.premultipliedAlpha = true' ); + error( 'WebGLState: MultiplyBlending requires material.premultipliedAlpha = true' ); break; default: - console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + error( 'WebGLState: Invalid blending: ', blending ); break; } @@ -47042,11 +48232,17 @@ function WebGLState( gl, extensions ) { if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { - gl.polygonOffset( factor, units ); - currentPolygonOffsetFactor = factor; currentPolygonOffsetUnits = units; + if ( depthBuffer.getReversed() ) { + + factor = - factor; + + } + + gl.polygonOffset( factor, units ); + } } else { @@ -47150,9 +48346,9 @@ function WebGLState( gl, extensions ) { gl.compressedTexImage2D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47164,9 +48360,9 @@ function WebGLState( gl, extensions ) { gl.compressedTexImage3D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47178,9 +48374,9 @@ function WebGLState( gl, extensions ) { gl.texSubImage2D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47192,9 +48388,9 @@ function WebGLState( gl, extensions ) { gl.texSubImage3D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47206,9 +48402,9 @@ function WebGLState( gl, extensions ) { gl.compressedTexSubImage2D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47220,9 +48416,9 @@ function WebGLState( gl, extensions ) { gl.compressedTexSubImage3D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47234,9 +48430,9 @@ function WebGLState( gl, extensions ) { gl.texStorage2D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47248,9 +48444,9 @@ function WebGLState( gl, extensions ) { gl.texStorage3D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47262,9 +48458,9 @@ function WebGLState( gl, extensions ) { gl.texImage2D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47276,9 +48472,9 @@ function WebGLState( gl, extensions ) { gl.texImage3D( ...arguments ); - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLState:', error ); + error( 'WebGLState:', e ); } @@ -47548,8 +48744,12 @@ function getByteLength( width, height, format, type ) { // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_etc/ case RGB_ETC1_Format: case RGB_ETC2_Format: + case R11_EAC_Format: + case SIGNED_R11_EAC_Format: return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8; case RGBA_ETC2_EAC_Format: + case RG11_EAC_Format: + case SIGNED_RG11_EAC_Format: return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16; // https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/ @@ -47652,9 +48852,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, try { useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' - // eslint-disable-next-line compat/compat && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; + } catch ( err ) { // Ignore any errors @@ -47666,7 +48866,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Use OffscreenCanvas when available. Specially needed in web workers return useOffscreenCanvas ? - // eslint-disable-next-line compat/compat new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); } @@ -47711,7 +48910,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const context = canvas.getContext( '2d' ); context.drawImage( image, 0, 0, width, height ); - console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); + warn( 'WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); return canvas; @@ -47719,7 +48918,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( 'data' in image ) { - console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); + warn( 'WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); } @@ -47760,7 +48959,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; - console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); + warn( 'WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); } @@ -47873,7 +49072,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else if ( depthType === UnsignedShortType ) { glInternalFormat = _gl.DEPTH24_STENCIL8; - console.warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' ); + warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' ); } @@ -48103,7 +49302,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( textureUnit >= capabilities.maxTextures ) { - console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); + warn( 'WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); } @@ -48150,11 +49349,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( image === null ) { - console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); + warn( 'WebGLRenderer: Texture marked for update but no image data found.' ); } else if ( image.complete === false ) { - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); + warn( 'WebGLRenderer: Texture marked for update but image is incomplete' ); } else { @@ -48182,6 +49381,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, uploadTexture( textureProperties, texture, slot ); return; + } else if ( texture.isExternalTexture ) { + + textureProperties.__webglTexture = texture.sourceTexture ? texture.sourceTexture : null; + } state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); @@ -48207,7 +49410,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const textureProperties = properties.get( texture ); - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { + if ( texture.isCubeDepthTexture !== true && texture.version > 0 && textureProperties.__version !== texture.version ) { uploadCubeTexture( textureProperties, texture, slot ); return; @@ -48251,7 +49454,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) { - console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); + warn( 'WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); } @@ -48660,7 +49863,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); + warn( 'WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); } @@ -48716,7 +49919,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); + warn( 'WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); } @@ -49010,7 +50213,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); + warn( 'WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); } @@ -49199,7 +50402,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } // Setup storage for internal depth/stencil buffers and bind to correct framebuffer - function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { + function setupRenderBufferStorage( renderbuffer, renderTarget, useMultisample ) { _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); @@ -49212,15 +50415,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; // set up the attachment - const samples = getRenderTargetSamples( renderTarget ); - const isUseMultisampledRTT = useMultisampledRTT( renderTarget ); - if ( isUseMultisampledRTT ) { + if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, getRenderTargetSamples( renderTarget ), glInternalFormat, renderTarget.width, renderTarget.height ); - } else if ( isMultisample ) { + } else if ( useMultisample ) { - _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, getRenderTargetSamples( renderTarget ), glInternalFormat, renderTarget.width, renderTarget.height ); } else { @@ -49241,15 +50442,14 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); - const samples = getRenderTargetSamples( renderTarget ); - if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { + if ( useMultisampledRTT( renderTarget ) ) { - _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, getRenderTargetSamples( renderTarget ), glInternalFormat, renderTarget.width, renderTarget.height ); - } else if ( useMultisampledRTT( renderTarget ) ) { + } else if ( useMultisample ) { - multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, getRenderTargetSamples( renderTarget ), glInternalFormat, renderTarget.width, renderTarget.height ); } else { @@ -49266,10 +50466,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } // Setup resources for a Depth Texture for a FBO (needs an extension) - function setupDepthTexture( framebuffer, renderTarget ) { + function setupDepthTexture( framebuffer, renderTarget, cubeFace ) { - const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); - if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); + const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); @@ -49293,20 +50492,69 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - setTexture2D( renderTarget.depthTexture, 0 ); + if ( isCube ) { + + // For cube depth textures, initialize and bind without uploading image data + if ( textureProperties.__webglInit === undefined ) { + + textureProperties.__webglInit = true; + renderTarget.depthTexture.addEventListener( 'dispose', onTextureDispose ); + + } + + // Only create and allocate storage once + if ( textureProperties.__webglTexture === undefined ) { + + textureProperties.__webglTexture = _gl.createTexture(); + + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.depthTexture ); + + // Allocate storage for all 6 faces with correct depth texture format + const glFormat = utils.convert( renderTarget.depthTexture.format ); + const glType = utils.convert( renderTarget.depthTexture.type ); + + // Use proper internal format for depth textures + let glInternalFormat; + if ( renderTarget.depthTexture.format === DepthFormat ) { + + glInternalFormat = _gl.DEPTH_COMPONENT24; + + } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { + + glInternalFormat = _gl.DEPTH24_STENCIL8; + + } + + for ( let i = 0; i < 6; i ++ ) { + + _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); + + } + + } + + } else { + + setTexture2D( renderTarget.depthTexture, 0 ); + + } const webglDepthTexture = textureProperties.__webglTexture; const samples = getRenderTargetSamples( renderTarget ); + const glTextureType = isCube ? _gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace : _gl.TEXTURE_2D; + const glAttachmentType = renderTarget.depthTexture.format === DepthStencilFormat ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + if ( renderTarget.depthTexture.format === DepthFormat ) { if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, glAttachmentType, glTextureType, webglDepthTexture, 0, samples ); } else { - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, glAttachmentType, glTextureType, webglDepthTexture, 0 ); } @@ -49314,11 +50562,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, glAttachmentType, glTextureType, webglDepthTexture, 0, samples ); } else { - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, glAttachmentType, glTextureType, webglDepthTexture, 0 ); } @@ -49369,17 +50617,28 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { - if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); + if ( isCube ) { - const mipmaps = renderTarget.texture.mipmaps; + // For cube render targets with depth texture, setup each face + for ( let i = 0; i < 6; i ++ ) { - if ( mipmaps && mipmaps.length > 0 ) { + setupDepthTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, i ); - setupDepthTexture( renderTargetProperties.__webglFramebuffer[ 0 ], renderTarget ); + } } else { - setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); + const mipmaps = renderTarget.texture.mipmaps; + + if ( mipmaps && mipmaps.length > 0 ) { + + setupDepthTexture( renderTargetProperties.__webglFramebuffer[ 0 ], renderTarget, 0 ); + + } else { + + setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 0 ); + + } } @@ -49903,13 +51162,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( format !== RGBAFormat || type !== UnsignedByteType ) { - console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); + warn( 'WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); } } else { - console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); + error( 'WebGLTextures: Unsupported texture color space:', colorSpace ); } @@ -49961,6 +51220,12 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, this.setupFrameBufferTexture = setupFrameBufferTexture; this.useMultisampledRTT = useMultisampledRTT; + this.isReversedDepthBuffer = function () { + + return state.buffers.depth.getReversed(); + + }; + } function WebGLUtils( gl, extensions ) { @@ -50064,7 +51329,7 @@ function WebGLUtils( gl, extensions ) { // ETC - if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format || p === R11_EAC_Format || p === SIGNED_R11_EAC_Format || p === RG11_EAC_Format || p === SIGNED_RG11_EAC_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_etc' ); @@ -50072,6 +51337,10 @@ function WebGLUtils( gl, extensions ) { if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === R11_EAC_Format ) return extension.COMPRESSED_R11_EAC; + if ( p === SIGNED_R11_EAC_Format ) return extension.COMPRESSED_SIGNED_R11_EAC; + if ( p === RG11_EAC_Format ) return extension.COMPRESSED_RG11_EAC; + if ( p === SIGNED_RG11_EAC_Format ) return extension.COMPRESSED_SIGNED_RG11_EAC; } else { @@ -51150,7 +52419,7 @@ class WebXRManager extends EventDispatcher { if ( scope.isPresenting === true ) { - console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); + warn( 'WebXRManager: Cannot change framebuffer scale while presenting.' ); } @@ -51172,7 +52441,7 @@ class WebXRManager extends EventDispatcher { if ( scope.isPresenting === true ) { - console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); + warn( 'WebXRManager: Cannot change reference space type while presenting.' ); } @@ -51620,8 +52889,8 @@ class WebXRManager extends EventDispatcher { // inherit camera layers and enable eye layers (1 = left, 2 = right) cameraXR.layers.mask = camera.layers.mask | 0b110; - cameraL.layers.mask = cameraXR.layers.mask & 0b011; - cameraR.layers.mask = cameraXR.layers.mask & 0b101; + cameraL.layers.mask = cameraXR.layers.mask & -5; + cameraR.layers.mask = cameraXR.layers.mask & -3; const parent = camera.parent; const cameras = cameraXR.cameras; @@ -52015,6 +53284,12 @@ function WebGLMaterials( renderer, properties ) { refreshUniformsCommon( uniforms, material ); + if ( material.envMap ) { + + uniforms.envMapIntensity.value = material.envMapIntensity; + + } + } else if ( material.isMeshToonMaterial ) { refreshUniformsCommon( uniforms, material ); @@ -52025,6 +53300,12 @@ function WebGLMaterials( renderer, properties ) { refreshUniformsCommon( uniforms, material ); refreshUniformsPhong( uniforms, material ); + if ( material.envMap ) { + + uniforms.envMapIntensity.value = material.envMapIntensity; + + } + } else if ( material.isMeshStandardMaterial ) { refreshUniformsCommon( uniforms, material ); @@ -52638,7 +53919,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { } - console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); + error( 'WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); return 0; @@ -52893,11 +54174,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { } else if ( value.isTexture ) { - console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); + warn( 'WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); } else { - console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); + warn( 'WebGLRenderer: Unsupported uniform value type.', value ); } @@ -52946,6 +54227,137 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { } +/** + * Creates a texture directly from raw buffer data. + * + * The interpretation of the data depends on type and format: If the type is + * `UnsignedByteType`, a `Uint8Array` will be useful for addressing the + * texel data. If the format is `RGBAFormat`, data needs four values for + * one texel; Red, Green, Blue and Alpha (typically the opacity). + * + * @augments Texture + */ +class DataTexture extends Texture { + + /** + * Constructs a new data texture. + * + * @param {?TypedArray} [data=null] - The buffer data. + * @param {number} [width=1] - The width of the texture. + * @param {number} [height=1] - The height of the texture. + * @param {number} [format=RGBAFormat] - The texture format. + * @param {number} [type=UnsignedByteType] - The texture type. + * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping. + * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value. + * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value. + * @param {number} [magFilter=NearestFilter] - The mag filter value. + * @param {number} [minFilter=NearestFilter] - The min filter value. + * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value. + * @param {string} [colorSpace=NoColorSpace] - The color space. + */ + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { + + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isDataTexture = true; + + /** + * The image definition of a data texture. + * + * @type {{data:TypedArray,width:number,height:number}} + */ + this.image = { data: data, width: width, height: height }; + + /** + * Whether to generate mipmaps (if possible) for a texture. + * + * Overwritten and set to `false` by default. + * + * @type {boolean} + * @default false + */ + this.generateMipmaps = false; + + /** + * If set to `true`, the texture is flipped along the vertical axis when + * uploaded to the GPU. + * + * Overwritten and set to `false` by default. + * + * @type {boolean} + * @default false + */ + this.flipY = false; + + /** + * Specifies the alignment requirements for the start of each pixel row in memory. + * + * Overwritten and set to `1` by default. + * + * @type {boolean} + * @default 1 + */ + this.unpackAlignment = 1; + + } + +} + +/** + * Precomputed DFG LUT for Image-Based Lighting + * Resolution: 16x16 + * Samples: 4096 per texel + * Format: RG16F (2 half floats per texel: scale, bias) + */ + + +const DATA = new Uint16Array( [ + 0x30b5, 0x3ad1, 0x314c, 0x3a4d, 0x33d2, 0x391c, 0x35ef, 0x3828, 0x37f3, 0x36a6, 0x38d1, 0x3539, 0x3979, 0x3410, 0x39f8, 0x3252, 0x3a53, 0x30f0, 0x3a94, 0x2fc9, 0x3abf, 0x2e35, 0x3ada, 0x2d05, 0x3ae8, 0x2c1f, 0x3aed, 0x2ae0, 0x3aea, 0x29d1, 0x3ae1, 0x28ff, + 0x3638, 0x38e4, 0x364a, 0x38ce, 0x3699, 0x385e, 0x374e, 0x372c, 0x3839, 0x35a4, 0x38dc, 0x3462, 0x396e, 0x32c4, 0x39de, 0x3134, 0x3a2b, 0x3003, 0x3a59, 0x2e3a, 0x3a6d, 0x2ce1, 0x3a6e, 0x2bba, 0x3a5f, 0x2a33, 0x3a49, 0x290a, 0x3a2d, 0x2826, 0x3a0a, 0x26e8, + 0x3894, 0x36d7, 0x3897, 0x36c9, 0x38a3, 0x3675, 0x38bc, 0x35ac, 0x38ee, 0x349c, 0x393e, 0x3332, 0x3997, 0x3186, 0x39e2, 0x3038, 0x3a13, 0x2e75, 0x3a29, 0x2cf5, 0x3a2d, 0x2bac, 0x3a21, 0x29ff, 0x3a04, 0x28bc, 0x39dc, 0x2790, 0x39ad, 0x261a, 0x3978, 0x24fa, + 0x39ac, 0x34a8, 0x39ac, 0x34a3, 0x39ae, 0x3480, 0x39ae, 0x3423, 0x39b1, 0x330e, 0x39c2, 0x31a9, 0x39e0, 0x3063, 0x39fc, 0x2eb5, 0x3a0c, 0x2d1d, 0x3a14, 0x2bcf, 0x3a07, 0x29ff, 0x39e9, 0x28a3, 0x39be, 0x273c, 0x3989, 0x25b3, 0x394a, 0x2488, 0x3907, 0x2345, + 0x3a77, 0x3223, 0x3a76, 0x321f, 0x3a73, 0x3204, 0x3a6a, 0x31b3, 0x3a58, 0x3114, 0x3a45, 0x303b, 0x3a34, 0x2eb6, 0x3a26, 0x2d31, 0x3a1e, 0x2bef, 0x3a0b, 0x2a0d, 0x39ec, 0x28a1, 0x39c0, 0x271b, 0x3987, 0x2580, 0x3944, 0x2449, 0x38fa, 0x22bd, 0x38ac, 0x2155, + 0x3b07, 0x2fca, 0x3b06, 0x2fca, 0x3b00, 0x2fb8, 0x3af4, 0x2f7c, 0x3adb, 0x2eea, 0x3ab4, 0x2e00, 0x3a85, 0x2cec, 0x3a5e, 0x2bc5, 0x3a36, 0x2a00, 0x3a0d, 0x2899, 0x39dc, 0x2707, 0x39a0, 0x2562, 0x395a, 0x2424, 0x390b, 0x2268, 0x38b7, 0x20fd, 0x385f, 0x1fd1, + 0x3b69, 0x2cb9, 0x3b68, 0x2cbb, 0x3b62, 0x2cbb, 0x3b56, 0x2cae, 0x3b3b, 0x2c78, 0x3b0d, 0x2c0a, 0x3acf, 0x2ae3, 0x3a92, 0x2998, 0x3a54, 0x2867, 0x3a17, 0x26d0, 0x39d3, 0x253c, 0x3989, 0x2402, 0x3935, 0x2226, 0x38dc, 0x20bd, 0x387d, 0x1f54, 0x381d, 0x1db3, + 0x3ba9, 0x296b, 0x3ba8, 0x296f, 0x3ba3, 0x297b, 0x3b98, 0x2987, 0x3b7f, 0x2976, 0x3b4e, 0x2927, 0x3b0e, 0x2895, 0x3ac2, 0x27b7, 0x3a73, 0x263b, 0x3a23, 0x24e7, 0x39d0, 0x239b, 0x3976, 0x21d9, 0x3917, 0x207e, 0x38b2, 0x1ee7, 0x384b, 0x1d53, 0x37c7, 0x1c1e, + 0x3bd2, 0x25cb, 0x3bd1, 0x25d3, 0x3bcd, 0x25f0, 0x3bc2, 0x261f, 0x3bad, 0x2645, 0x3b7d, 0x262d, 0x3b3e, 0x25c4, 0x3aec, 0x250f, 0x3a93, 0x243a, 0x3a32, 0x22ce, 0x39d0, 0x215b, 0x3969, 0x202a, 0x38fe, 0x1e6e, 0x388f, 0x1cf1, 0x381f, 0x1b9b, 0x3762, 0x19dd, + 0x3be9, 0x21ab, 0x3be9, 0x21b7, 0x3be5, 0x21e5, 0x3bdd, 0x2241, 0x3bc9, 0x22a7, 0x3ba0, 0x22ec, 0x3b62, 0x22cd, 0x3b0f, 0x2247, 0x3aae, 0x2175, 0x3a44, 0x2088, 0x39d4, 0x1f49, 0x3960, 0x1dbe, 0x38e9, 0x1c77, 0x3870, 0x1ae8, 0x37f1, 0x1953, 0x3708, 0x181b, + 0x3bf6, 0x1cea, 0x3bf6, 0x1cfb, 0x3bf3, 0x1d38, 0x3bec, 0x1dbd, 0x3bda, 0x1e7c, 0x3bb7, 0x1f25, 0x3b7d, 0x1f79, 0x3b2c, 0x1f4c, 0x3ac6, 0x1ea6, 0x3a55, 0x1dbb, 0x39da, 0x1cbd, 0x395a, 0x1b9d, 0x38d8, 0x1a00, 0x3855, 0x18ac, 0x37ab, 0x173c, 0x36b7, 0x1598, + 0x3bfc, 0x1736, 0x3bfc, 0x1759, 0x3bf9, 0x17e7, 0x3bf4, 0x1896, 0x3be4, 0x1997, 0x3bc6, 0x1aa8, 0x3b91, 0x1b84, 0x3b43, 0x1bd2, 0x3ade, 0x1b8a, 0x3a65, 0x1acd, 0x39e2, 0x19d3, 0x3957, 0x18cd, 0x38ca, 0x17b3, 0x383e, 0x1613, 0x376d, 0x14bf, 0x366f, 0x135e, + 0x3bff, 0x101b, 0x3bff, 0x1039, 0x3bfc, 0x10c8, 0x3bf9, 0x1226, 0x3bea, 0x1428, 0x3bcf, 0x1584, 0x3b9f, 0x16c5, 0x3b54, 0x179a, 0x3af0, 0x17ce, 0x3a76, 0x1771, 0x39ea, 0x16a4, 0x3956, 0x15a7, 0x38bf, 0x14a7, 0x3829, 0x1379, 0x3735, 0x11ea, 0x362d, 0x10a1, + 0x3c00, 0x061b, 0x3c00, 0x066a, 0x3bfe, 0x081c, 0x3bfa, 0x0a4c, 0x3bed, 0x0d16, 0x3bd5, 0x0fb3, 0x3ba9, 0x114d, 0x3b63, 0x127c, 0x3b01, 0x132f, 0x3a85, 0x1344, 0x39f4, 0x12d2, 0x3957, 0x120d, 0x38b5, 0x1122, 0x3817, 0x103c, 0x3703, 0x0ed3, 0x35f0, 0x0d6d, + 0x3c00, 0x007a, 0x3c00, 0x0089, 0x3bfe, 0x011d, 0x3bfb, 0x027c, 0x3bf0, 0x04fa, 0x3bda, 0x0881, 0x3bb1, 0x0acd, 0x3b6f, 0x0c97, 0x3b10, 0x0d7b, 0x3a93, 0x0df1, 0x39fe, 0x0def, 0x3959, 0x0d8a, 0x38af, 0x0ce9, 0x3808, 0x0c31, 0x36d5, 0x0af0, 0x35b9, 0x09a3, + 0x3c00, 0x0000, 0x3c00, 0x0001, 0x3bff, 0x0015, 0x3bfb, 0x0059, 0x3bf2, 0x00fd, 0x3bdd, 0x01df, 0x3bb7, 0x031c, 0x3b79, 0x047c, 0x3b1d, 0x05d4, 0x3aa0, 0x06d5, 0x3a08, 0x075a, 0x395d, 0x075e, 0x38aa, 0x06f7, 0x37f4, 0x0648, 0x36ac, 0x0576, 0x3586, 0x049f +] ); + +let lut = null; + +function getDFGLUT() { + + if ( lut === null ) { + + lut = new DataTexture( DATA, 16, 16, RGFormat, HalfFloatType ); + lut.name = 'DFG_LUT'; + lut.minFilter = LinearFilter; + lut.magFilter = LinearFilter; + lut.wrapS = ClampToEdgeWrapping; + lut.wrapT = ClampToEdgeWrapping; + lut.generateMipmaps = false; + lut.needsUpdate = true; + + } + + return lut; + +} + /** * This renderer uses WebGL 2 to display scenes. * @@ -52972,6 +54384,7 @@ class WebGLRenderer { powerPreference = 'default', failIfMajorPerformanceCaveat = false, reversedDepthBuffer = false, + outputBufferType = UnsignedByteType, } = parameters; /** @@ -53001,6 +54414,23 @@ class WebGLRenderer { } + const _outputBufferType = outputBufferType; + + const INTEGER_FORMATS = new Set( [ + RGBAIntegerFormat, + RGIntegerFormat, + RedIntegerFormat + ] ); + + const UNSIGNED_TYPES = new Set( [ + UnsignedByteType, + UnsignedIntType, + UnsignedShortType, + UnsignedInt248Type, + UnsignedShort4444Type, + UnsignedShort5551Type + ] ); + const uintClearColor = new Uint32Array( 4 ); const intClearColor = new Int32Array( 4 ); @@ -53013,16 +54443,20 @@ class WebGLRenderer { const renderListStack = []; const renderStateStack = []; + // internal render target for non-UnsignedByteType color buffer + + let output = null; + // public properties /** - * A canvas where the renderer draws its output.This is automatically created by the renderer + * A canvas where the renderer draws its output. This is automatically created by the renderer * in the constructor (if not provided already); you just need to add it to your page like so: * ```js * document.body.appendChild( renderer.domElement ); * ``` * - * @type {DOMElement} + * @type {HTMLCanvasElement|OffscreenCanvas} */ this.domElement = canvas; @@ -53032,7 +54466,7 @@ class WebGLRenderer { * - `checkShaderErrors`: If it is `true`, defines whether material shader programs are * checked for errors during compilation and linkage process. It may be useful to disable * this check in production for performance gain. It is strongly recommended to keep these - * checks enabled during development. If the shader does not compile and link - it will not + * checks enabled during development. If the shader does not compile and link, it will not * work and associated material will not render. * - `onShaderError(gl, program, glVertexShader,glFragmentShader)`: A callback function that * can be used for custom error reporting. The callback receives the WebGL context, an instance @@ -53273,15 +54707,15 @@ class WebGLRenderer { } - } catch ( error ) { + } catch ( e ) { - console.error( 'THREE.WebGLRenderer: ' + error.message ); - throw error; + error( 'WebGLRenderer: ' + e.message ); + throw e; } let extensions, capabilities, state, info; - let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let properties, textures, environments, attributes, geometries, objects; let programCache, materials, renderLists, renderStates, clipping, shadowMap; let background, morphtargets, bufferRenderer, indexedBufferRenderer; @@ -53308,19 +54742,18 @@ class WebGLRenderer { info = new WebGLInfo( _gl ); properties = new WebGLProperties(); textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); - cubemaps = new WebGLCubeMaps( _this ); - cubeuvmaps = new WebGLCubeUVMaps( _this ); + environments = new WebGLEnvironments( _this ); attributes = new WebGLAttributes( _gl ); bindingStates = new WebGLBindingStates( _gl, attributes ); geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); - objects = new WebGLObjects( _gl, geometries, attributes, info ); + objects = new WebGLObjects( _gl, geometries, attributes, bindingStates, info ); morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); clipping = new WebGLClipping( properties ); - programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); + programCache = new WebGLPrograms( _this, environments, extensions, capabilities, bindingStates, clipping ); materials = new WebGLMaterials( _this, properties ); renderLists = new WebGLRenderLists(); renderStates = new WebGLRenderStates( extensions ); - background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + background = new WebGLBackground( _this, environments, state, objects, _alpha, premultipliedAlpha ); shadowMap = new WebGLShadowMap( _this, objects, capabilities ); uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); @@ -53408,6 +54841,14 @@ class WebGLRenderer { initGLContext(); + // initialize internal render target for non-UnsignedByteType color buffer + + if ( _outputBufferType !== UnsignedByteType ) { + + output = new WebGLOutput( _outputBufferType, canvas.width, canvas.height, depth, stencil ); + + } + // xr const xr = new WebXRManager( _this, _gl ); @@ -53512,7 +54953,7 @@ class WebGLRenderer { if ( xr.isPresenting ) { - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + warn( 'WebGLRenderer: Can\'t change size while VR device is presenting.' ); return; } @@ -53530,6 +54971,12 @@ class WebGLRenderer { } + if ( output !== null ) { + + output.setSize( canvas.width, canvas.height ); + + } + this.setViewport( 0, 0, width, height ); }; @@ -53573,6 +55020,39 @@ class WebGLRenderer { }; + /** + * Sets the post-processing effects to be applied after rendering. + * + * @param {Array} effects - An array of post-processing effects. + */ + this.setEffects = function ( effects ) { + + if ( _outputBufferType === UnsignedByteType ) { + + console.error( 'THREE.WebGLRenderer: setEffects() requires outputBufferType set to HalfFloatType or FloatType.' ); + return; + + } + + if ( effects ) { + + for ( let i = 0; i < effects.length; i ++ ) { + + if ( effects[ i ].isOutputPass === true ) { + + console.warn( 'THREE.WebGLRenderer: OutputPass is not needed in setEffects(). Tone mapping and color space conversion are applied automatically.' ); + break; + + } + + } + + } + + output.setEffects( effects || [] ); + + }; + /** * Returns the current viewport definition. * @@ -53774,9 +55254,7 @@ class WebGLRenderer { if ( _currentRenderTarget !== null ) { const targetFormat = _currentRenderTarget.texture.format; - isIntegerFormat = targetFormat === RGBAIntegerFormat || - targetFormat === RGIntegerFormat || - targetFormat === RedIntegerFormat; + isIntegerFormat = INTEGER_FORMATS.has( targetFormat ); } @@ -53785,12 +55263,7 @@ class WebGLRenderer { if ( isIntegerFormat ) { const targetType = _currentRenderTarget.texture.type; - const isUnsignedType = targetType === UnsignedByteType || - targetType === UnsignedIntType || - targetType === UnsignedShortType || - targetType === UnsignedInt248Type || - targetType === UnsignedShort4444Type || - targetType === UnsignedShort5551Type; + const isUnsignedType = UNSIGNED_TYPES.has( targetType ); const clearColor = background.getClearColor(); const a = background.getClearAlpha(); @@ -53837,7 +55310,11 @@ class WebGLRenderer { } - _gl.clear( bits ); + if ( bits !== 0 ) { + + _gl.clear( bits ); + + } }; @@ -53882,8 +55359,7 @@ class WebGLRenderer { renderLists.dispose(); renderStates.dispose(); properties.dispose(); - cubemaps.dispose(); - cubeuvmaps.dispose(); + environments.dispose(); objects.dispose(); bindingStates.dispose(); uniformsGroups.dispose(); @@ -53904,7 +55380,7 @@ class WebGLRenderer { event.preventDefault(); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + log( 'WebGLRenderer: Context Lost.' ); _isContextLost = true; @@ -53912,7 +55388,7 @@ class WebGLRenderer { function onContextRestore( /* event */ ) { - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + log( 'WebGLRenderer: Context Restored.' ); _isContextLost = false; @@ -53934,7 +55410,7 @@ class WebGLRenderer { function onContextCreationError( event ) { - console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); + error( 'WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); } @@ -54107,7 +55583,7 @@ class WebGLRenderer { if ( object._multiDrawInstances !== null ) { // @deprecated, r174 - warnOnce( 'THREE.WebGLRenderer: renderMultiDrawInstances has been deprecated and will be removed in r184. Append to renderMultiDraw arguments and use indirection.' ); + warnOnce( 'WebGLRenderer: renderMultiDrawInstances has been deprecated and will be removed in r184. Append to renderMultiDraw arguments and use indirection.' ); renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); } else { @@ -54383,6 +55859,13 @@ class WebGLRenderer { if ( typeof self !== 'undefined' ) animation.setContext( self ); + /** + * Applications are advised to always define the animation loop + * with this method and not manually with `requestAnimationFrame()` + * for best compatibility. + * + * @param {?onAnimationCallback} callback - The application's animation loop. + */ this.setAnimationLoop = function ( callback ) { onAnimationFrameCallback = callback; @@ -54415,13 +55898,19 @@ class WebGLRenderer { if ( camera !== undefined && camera.isCamera !== true ) { - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + error( 'WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); return; } if ( _isContextLost === true ) return; + // use internal render target for HalfFloatType color buffer (only when tone mapping is enabled) + + const isXRPresenting = xr.enabled === true && xr.isPresenting === true; + + const useOutput = output !== null && ( _currentRenderTarget === null || isXRPresenting ) && output.begin( _this, _currentRenderTarget ); + // update scene graph if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); @@ -54430,7 +55919,7 @@ class WebGLRenderer { if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - if ( xr.enabled === true && xr.isPresenting === true ) { + if ( xr.enabled === true && xr.isPresenting === true && ( output === null || output.isCompositing() === false ) ) { if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); @@ -54502,46 +55991,52 @@ class WebGLRenderer { if ( this.info.autoReset === true ) this.info.reset(); - // render scene + // render scene (skip if first effect is a render pass - it will render the scene itself) - const opaqueObjects = currentRenderList.opaque; - const transmissiveObjects = currentRenderList.transmissive; + const skipSceneRender = useOutput && output.hasRenderPass(); - currentRenderState.setupLights(); + if ( skipSceneRender === false ) { - if ( camera.isArrayCamera ) { + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; - const cameras = camera.cameras; + currentRenderState.setupLights(); - if ( transmissiveObjects.length > 0 ) { + if ( camera.isArrayCamera ) { - for ( let i = 0, l = cameras.length; i < l; i ++ ) { + const cameras = camera.cameras; - const camera2 = cameras[ i ]; + if ( transmissiveObjects.length > 0 ) { + + for ( let i = 0, l = cameras.length; i < l; i ++ ) { + + const camera2 = cameras[ i ]; - renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 ); + renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 ); + + } } - } + if ( _renderBackground ) background.render( scene ); - if ( _renderBackground ) background.render( scene ); + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - for ( let i = 0, l = cameras.length; i < l; i ++ ) { + const camera2 = cameras[ i ]; - const camera2 = cameras[ i ]; + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - renderScene( currentRenderList, scene, camera2, camera2.viewport ); + } - } + } else { - } else { + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); + if ( _renderBackground ) background.render( scene ); - if ( _renderBackground ) background.render( scene ); + renderScene( currentRenderList, scene, camera ); - renderScene( currentRenderList, scene, camera ); + } } @@ -54559,6 +56054,14 @@ class WebGLRenderer { } + // copy from internal render target to canvas using fullscreen quad + + if ( useOutput ) { + + output.end( _this ); + + } + // if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); @@ -54713,9 +56216,7 @@ class WebGLRenderer { function renderScene( currentRenderList, scene, camera, viewport ) { - const opaqueObjects = currentRenderList.opaque; - const transmissiveObjects = currentRenderList.transmissive; - const transparentObjects = currentRenderList.transparent; + const { opaque: opaqueObjects, transmissive: transmissiveObjects, transparent: transparentObjects } = currentRenderList; currentRenderState.setupLightsView( camera ); @@ -54749,11 +56250,13 @@ class WebGLRenderer { if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) { + const hasHalfFloatSupport = extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ); + currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, { generateMipmaps: true, - type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType, + type: hasHalfFloatSupport ? HalfFloatType : UnsignedByteType, minFilter: LinearMipmapLinearFilter, - samples: 4, + samples: capabilities.samples, stencilBuffer: stencil, resolveDepthBuffer: false, resolveStencilBuffer: false, @@ -54820,10 +56323,7 @@ class WebGLRenderer { const renderItem = transmissiveObjects[ i ]; - const object = renderItem.object; - const geometry = renderItem.geometry; - const material = renderItem.material; - const group = renderItem.group; + const { object, geometry, material, group } = renderItem; if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { @@ -54870,9 +56370,7 @@ class WebGLRenderer { const renderItem = renderList[ i ]; - const object = renderItem.object; - const geometry = renderItem.geometry; - const group = renderItem.group; + const { object, geometry, group } = renderItem; let material = renderItem.material; if ( material.allowOverride === true && overrideMaterial !== null ) { @@ -54940,9 +56438,11 @@ class WebGLRenderer { // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.environment = ( material.isMeshStandardMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial ) ? scene.environment : null; materialProperties.fog = scene.fog; - materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + + const usePMREM = material.isMeshStandardMaterial || ( material.isMeshLambertMaterial && ! material.envMap ) || ( material.isMeshPhongMaterial && ! material.envMap ); + materialProperties.envMap = environments.get( material.envMap || materialProperties.environment, usePMREM ); materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; if ( programs === undefined ) { @@ -55015,12 +56515,9 @@ class WebGLRenderer { uniforms.pointLightShadows.value = lights.state.pointShadow; uniforms.hemisphereLights.value = lights.state.hemi; - uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; - uniforms.spotShadowMap.value = lights.state.spotShadowMap; uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; uniforms.spotLightMap.value = lights.state.spotLightMap; - uniforms.pointShadowMap.value = lights.state.pointShadowMap; uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; // TODO (abelnation): add area lights shadow info to uniforms @@ -55076,9 +56573,10 @@ class WebGLRenderer { textures.resetTextureUnits(); const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; + const environment = ( material.isMeshStandardMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial ) ? scene.environment : null; const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); - const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const usePMREM = material.isMeshStandardMaterial || ( material.isMeshLambertMaterial && ! material.envMap ) || ( material.isMeshPhongMaterial && ! material.envMap ); + const envMap = environments.get( material.envMap || environment, usePMREM ); const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); const morphTargets = !! geometry.morphAttributes.position; @@ -55326,6 +56824,30 @@ class WebGLRenderer { } + // Pre-allocate texture units for shadow samplers before setting data textures + if ( materialProperties.needsLights ) { + + // Set shadow map uniforms first to ensure they get the first texture units + if ( lights.state.directionalShadowMap.length > 0 ) { + + p_uniforms.setValue( _gl, 'directionalShadowMap', lights.state.directionalShadowMap, textures ); + + } + + if ( lights.state.spotShadowMap.length > 0 ) { + + p_uniforms.setValue( _gl, 'spotShadowMap', lights.state.spotShadowMap, textures ); + + } + + if ( lights.state.pointShadowMap.length > 0 ) { + + p_uniforms.setValue( _gl, 'pointShadowMap', lights.state.pointShadowMap, textures ); + + } + + } + // skinning and morph target uniforms must be set even if material didn't change // auto-setting of texture unit for bone and morph texture must go before other textures // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures @@ -55379,19 +56901,16 @@ class WebGLRenderer { } - // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 + if ( ( material.isMeshStandardMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial ) && material.envMap === null && scene.environment !== null ) { - if ( material.isMeshGouraudMaterial && material.envMap !== null ) { - - m_uniforms.envMap.value = envMap; - - m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? -1 : 1; + m_uniforms.envMapIntensity.value = scene.environmentIntensity; } - if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) { + // Set DFG LUT for physically-based materials + if ( m_uniforms.dfgLUT !== undefined ) { - m_uniforms.envMapIntensity.value = scene.environmentIntensity; + m_uniforms.dfgLUT.value = getDFGLUT(); } @@ -55573,7 +57092,6 @@ class WebGLRenderer { _currentActiveCubeFace = activeCubeFace; _currentActiveMipmapLevel = activeMipmapLevel; - let useDefaultFramebuffer = true; let framebuffer = null; let isCube = false; let isRenderTarget3D = false; @@ -55584,9 +57102,21 @@ class WebGLRenderer { if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - // We need to make sure to rebind the framebuffer. - state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - useDefaultFramebuffer = false; + // Externally-managed framebuffer (e.g. XR) + // Bind to the stored framebuffer (may be null for default, or a WebGLFramebuffer) + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; + + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); + + _currentMaterialId = -1; + + return; } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { @@ -55685,7 +57215,7 @@ class WebGLRenderer { const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( framebufferBound && useDefaultFramebuffer ) { + if ( framebufferBound ) { state.drawBuffers( renderTarget, framebuffer ); @@ -55741,7 +57271,7 @@ class WebGLRenderer { if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + error( 'WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); return; } @@ -55764,16 +57294,20 @@ class WebGLRenderer { const textureFormat = texture.format; const textureType = texture.type; + // when using MRT, select the correct color buffer for the subsequent read command + + if ( renderTarget.textures.length > 1 ) _gl.readBuffer( _gl.COLOR_ATTACHMENT0 + textureIndex ); + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + error( 'WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); return; } if ( ! capabilities.textureTypeReadable( textureType ) ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + error( 'WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); return; } @@ -55782,10 +57316,6 @@ class WebGLRenderer { if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - // when using MRT, select the correct color buffer for the subsequent read command - - if ( renderTarget.textures.length > 1 ) _gl.readBuffer( _gl.COLOR_ATTACHMENT0 + textureIndex ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); } @@ -55846,6 +57376,11 @@ class WebGLRenderer { const textureFormat = texture.format; const textureType = texture.type; + // when using MRT, select the correct color buffer for the subsequent read command + + if ( renderTarget.textures.length > 1 ) _gl.readBuffer( _gl.COLOR_ATTACHMENT0 + textureIndex ); + + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); @@ -55862,10 +57397,6 @@ class WebGLRenderer { _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); - // when using MRT, select the correct color buffer for the subsequent read command - - if ( renderTarget.textures.length > 1 ) _gl.readBuffer( _gl.COLOR_ATTACHMENT0 + textureIndex ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); // reset the frame buffer to the currently set buffer before waiting @@ -55935,27 +57466,9 @@ class WebGLRenderer { * @param {?(Box2|Box3)} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional. * @param {?(Vector2|Vector3)} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional. * @param {number} [srcLevel=0] - The source mipmap level to copy. - * @param {?number} [dstLevel=null] - The destination mipmap level. + * @param {?number} [dstLevel=0] - The destination mipmap level. */ - this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = null ) { - - // support the previous signature with just a single dst mipmap level - if ( dstLevel === null ) { - - if ( srcLevel !== 0 ) { - - // @deprecated, r171 - warnOnce( 'WebGLRenderer: copyTextureToTexture function signature has changed to support src and dst mipmap levels.' ); - dstLevel = srcLevel; - srcLevel = 0; - - } else { - - dstLevel = 0; - - } - - } + this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) { // gather the necessary dimensions to copy let width, height, depth, minX, minY, minZ; @@ -56620,89 +58133,6 @@ class InstancedBufferAttribute extends BufferAttribute { } -/** - * Creates a texture directly from raw buffer data. - * - * The interpretation of the data depends on type and format: If the type is - * `UnsignedByteType`, a `Uint8Array` will be useful for addressing the - * texel data. If the format is `RGBAFormat`, data needs four values for - * one texel; Red, Green, Blue and Alpha (typically the opacity). - * - * @augments Texture - */ -class DataTexture extends Texture { - - /** - * Constructs a new data texture. - * - * @param {?TypedArray} [data=null] - The buffer data. - * @param {number} [width=1] - The width of the texture. - * @param {number} [height=1] - The height of the texture. - * @param {number} [format=RGBAFormat] - The texture format. - * @param {number} [type=UnsignedByteType] - The texture type. - * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping. - * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value. - * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value. - * @param {number} [magFilter=NearestFilter] - The mag filter value. - * @param {number} [minFilter=NearestFilter] - The min filter value. - * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value. - * @param {string} [colorSpace=NoColorSpace] - The color space. - */ - constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { - - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); - - /** - * This flag can be used for type testing. - * - * @type {boolean} - * @readonly - * @default true - */ - this.isDataTexture = true; - - /** - * The image definition of a data texture. - * - * @type {{data:TypedArray,width:number,height:number}} - */ - this.image = { data: data, width: width, height: height }; - - /** - * Whether to generate mipmaps (if possible) for a texture. - * - * Overwritten and set to `false` by default. - * - * @type {boolean} - * @default false - */ - this.generateMipmaps = false; - - /** - * If set to `true`, the texture is flipped along the vertical axis when - * uploaded to the GPU. - * - * Overwritten and set to `false` by default. - * - * @type {boolean} - * @default false - */ - this.flipY = false; - - /** - * Specifies the alignment requirements for the start of each pixel row in memory. - * - * Overwritten and set to `1` by default. - * - * @type {boolean} - * @default 1 - */ - this.unpackAlignment = 1; - - } - -} - const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); @@ -56753,6 +58183,15 @@ class InstancedMesh extends Mesh { */ this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); + /** + * Represents the local transformation of all instances of the previous frame. + * Required for computing velocity. Maintained in {@link InstanceNode}. + * + * @type {?InstancedBufferAttribute} + * @default null + */ + this.previousInstanceMatrix = null; + /** * Represents the color of all instances. You have to set its * {@link BufferAttribute#needsUpdate} flag to true if you modify instanced data @@ -56882,6 +58321,8 @@ class InstancedMesh extends Mesh { this.instanceMatrix.copy( source.instanceMatrix ); + if ( source.previousInstanceMatrix !== null ) this.previousInstanceMatrix = source.previousInstanceMatrix.clone(); + if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone(); if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone(); @@ -57280,7 +58721,7 @@ let Line$1 = class Line extends Object3D { * morph targets name, the value its attribute index. This member is `undefined` * by default and only set when morph targets are detected in the geometry. * - * @type {Object|undefined} + * @type {Object|undefined} * @default undefined */ this.morphTargetDictionary = undefined; @@ -57342,7 +58783,7 @@ let Line$1 = class Line extends Object3D { } else { - console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); + warn( 'Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); } @@ -57583,7 +59024,7 @@ class LineSegments extends Line$1 { } else { - console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); + warn( 'LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); } @@ -57680,7 +59121,7 @@ class PointsMaterial extends Material { /** * Defines the size of the points in pixels. * - * Might be capped if the value exceeds hardware dependent parameters like [gl.ALIASED_POINT_SIZE_RANGE]{@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParamete}. + * Might be capped if the value exceeds hardware dependent parameters like [gl.ALIASED_POINT_SIZE_RANGE](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParamete). * * @type {number} * @default 1 @@ -57781,7 +59222,7 @@ class Points extends Object3D { * morph targets name, the value its attribute index. This member is `undefined` * by default and only set when morph targets are detected in the geometry. * - * @type {Object|undefined} + * @type {Object|undefined} * @default undefined */ this.morphTargetDictionary = undefined; @@ -58005,6 +59446,7 @@ class CanvasTexture extends Texture { * ``` * * @augments BufferGeometry + * @demo scenes/geometry-browser.html#CircleGeometry */ class CircleGeometry extends BufferGeometry { @@ -58186,7 +59628,7 @@ class Curve { */ getPoint( /* t, optionalTarget */ ) { - console.warn( 'THREE.Curve: .getPoint() not implemented.' ); + warn( 'Curve: .getPoint() not implemented.' ); } @@ -59244,7 +60686,13 @@ class CatmullRomCurve3 extends Curve { } -// Bezier Curves formulas obtained from: https://en.wikipedia.org/wiki/B%C3%A9zier_curve +/** + * Interpolations contains spline and Bézier functions internally used by concrete curve classes. + * + * Bezier Curves formulas obtained from: https://en.wikipedia.org/wiki/B%C3%A9zier_curve + * + * @module Interpolations + */ /** * Computes a point on a Catmull-Rom spline. @@ -61026,8 +62474,8 @@ class Shape extends Path$1 { } /* eslint-disable */ -// copy of mapbox/earcut version 3.0.1 -// https://github.com/mapbox/earcut/tree/v3.0.1 +// copy of mapbox/earcut version 3.0.2 +// https://github.com/mapbox/earcut/tree/v3.0.2 function earcut(data, holeIndices, dim = 2) { @@ -61044,10 +62492,10 @@ function earcut(data, holeIndices, dim = 2) { // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox if (data.length > 80 * dim) { - minX = Infinity; - minY = Infinity; - let maxX = -Infinity; - let maxY = -Infinity; + minX = data[0]; + minY = data[1]; + let maxX = minX; + let maxY = minY; for (let i = dim; i < outerLen; i += dim) { const x = data[i]; @@ -61323,7 +62771,7 @@ function compareXYSlope(a, b) { return result; } -// find a bridge between vertices that connects hole with an outer ring and and link it +// find a bridge between vertices that connects hole with an outer ring and link it function eliminateHole(hole, outerNode) { const bridge = findHoleBridge(hole, outerNode); if (!bridge) { @@ -61661,6 +63109,12 @@ function signedArea(data, start, end, dim) { return sum; } +/** + * An implementation of the earcut polygon triangulation algorithm. + * The code is a port of [mapbox/earcut](https://github.com/mapbox/earcut). + * + * @see https://github.com/mapbox/earcut + */ class Earcut { /** @@ -61811,6 +63265,7 @@ function addContour( vertices, contour ) { * ``` * * @augments BufferGeometry + * @demo scenes/geometry-browser.html#ExtrudeGeometry */ class ExtrudeGeometry extends BufferGeometry { @@ -61895,11 +63350,11 @@ class ExtrudeGeometry extends BufferGeometry { // SETUP TNB variables - // TODO1 - have a .isClosed in spline? + const isClosed = extrudePath.isCatmullRomCurve3 ? extrudePath.closed : false; - splineTube = extrudePath.computeFrenetFrames( steps, false ); + splineTube = extrudePath.computeFrenetFrames( steps, isClosed ); - // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); + // log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); binormal = new Vector3(); normal = new Vector3(); @@ -62004,7 +63459,7 @@ class ExtrudeGeometry extends BufferGeometry { function scalePt2( pt, vec, size ) { - if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); + if ( ! vec ) error( 'ExtrudeGeometry: vec does not exist' ); return pt.clone().addScaledVector( vec, size ); @@ -62119,14 +63574,14 @@ class ExtrudeGeometry extends BufferGeometry { if ( direction_eq ) { - // console.log("Warning: lines are a straight sequence"); + // log("Warning: lines are a straight sequence"); v_trans_x = - v_prev_y; v_trans_y = v_prev_x; shrink_by = Math.sqrt( v_prev_lensq ); } else { - // console.log("Warning: lines are a straight spike"); + // log("Warning: lines are a straight spike"); v_trans_x = v_prev_x; v_trans_y = v_prev_y; shrink_by = Math.sqrt( v_prev_lensq / 2 ); @@ -62148,7 +63603,7 @@ class ExtrudeGeometry extends BufferGeometry { if ( k === il ) k = 0; // (j)---(i)---(k) - // console.log('i,j,k', i, j , k) + // log('i,j,k', i, j , k) contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); @@ -62445,7 +63900,7 @@ class ExtrudeGeometry extends BufferGeometry { let k = i - 1; if ( k < 0 ) k = contour.length - 1; - //console.log('b', i,j, i-1, k,vertices.length); + //log('b', i,j, i-1, k,vertices.length); for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) { @@ -62685,6 +64140,7 @@ function toJSON$1( shapes, options, data ) { * ``` * * @augments BufferGeometry + * @demo scenes/geometry-browser.html#SphereGeometry */ class SphereGeometry extends BufferGeometry { @@ -62847,9 +64303,9 @@ class SphereGeometry extends BufferGeometry { * A standard physically based material, using Metallic-Roughness workflow. * * Physically based rendering (PBR) has recently become the standard in many - * 3D applications, such as [Unity]{@link https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/}, - * [Unreal]{@link https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/} and - * [3D Studio Max]{@link http://area.autodesk.com/blogs/the-3ds-max-blog/what039s-new-for-rendering-in-3ds-max-2017}. + * 3D applications, such as [Unity](https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/), + * [Unreal](https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/) and + * [3D Studio Max](http://area.autodesk.com/blogs/the-3ds-max-blog/what039s-new-for-rendering-in-3ds-max-2017). * * This approach differs from older approaches in that instead of using * approximations for the way in which light interacts with a surface, a @@ -62865,16 +64321,17 @@ class SphereGeometry extends BufferGeometry { * Note that for best results you should always specify an environment map when using this material. * * For a non-technical introduction to the concept of PBR and how to set up a - * PBR material, check out these articles by the people at [marmoset]{@link https://www.marmoset.co}: + * PBR material, check out these articles by the people at [marmoset](https://www.marmoset.co): * - * - [Basic Theory of Physically Based Rendering]{@link https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/} - * - [Physically Based Rendering and You Can Too]{@link https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/} + * - [Basic Theory of Physically Based Rendering](https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/) + * - [Physically Based Rendering and You Can Too](https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/) * * Technical details of the approach used in three.js (and most other PBR systems) can be found is this - * [paper from Disney]{@link https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf} + * [paper from Disney](https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf) * (pdf), by Brent Burley. * * @augments Material + * @demo scenes/material-browser.html#MeshStandardMaterial */ class MeshStandardMaterial extends Material { @@ -63284,6 +64741,7 @@ class MeshStandardMaterial extends Material { * best results, always specify an environment map when using this material. * * @augments MeshStandardMaterial + * @demo scenes/material-browser.html#MeshPhysicalMaterial */ class MeshPhysicalMaterial extends MeshStandardMaterial { @@ -63580,7 +65038,7 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { } /** - * The anisotropy strength. + * The anisotropy strength, from `0.0` to `1.0`. * * @type {number} * @default 0 @@ -63792,7 +65250,7 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { /** * A material for shiny surfaces with specular highlights. * - * The material uses a non-physically based [Blinn-Phong]{@link https://en.wikipedia.org/wiki/Blinn-Phong_shading_model} + * The material uses a non-physically based [Blinn-Phong](https://en.wikipedia.org/wiki/Blinn-Phong_shading_model) * model for calculating reflectance. Unlike the Lambertian model used in the * {@link MeshLambertMaterial} this can simulate shiny surfaces with specular * highlights (such as varnished wood). `MeshPhongMaterial` uses per-fragment shading. @@ -63802,6 +65260,7 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { * some graphical accuracy. * * @augments Material + * @demo scenes/material-browser.html#MeshPhongMaterial */ class MeshPhongMaterial extends Material { @@ -64068,6 +65527,14 @@ class MeshPhongMaterial extends Material { */ this.reflectivity = 1; + /** + * Scales the effect of the environment map by multiplying its color. + * + * @type {number} + * @default 1 + */ + this.envMapIntensity = 1.0; + /** * The index of refraction (IOR) of air (approximately 1) divided by the * index of refraction of the material. It is used with environment mapping @@ -64176,6 +65643,7 @@ class MeshPhongMaterial extends Material { this.envMapRotation.copy( source.envMapRotation ); this.combine = source.combine; this.reflectivity = source.reflectivity; + this.envMapIntensity = source.envMapIntensity; this.refractionRatio = source.refractionRatio; this.wireframe = source.wireframe; @@ -64197,6 +65665,7 @@ class MeshPhongMaterial extends Material { * A material implementing toon shading. * * @augments Material + * @demo scenes/material-browser.html#MeshToonMaterial */ class MeshToonMaterial extends Material { @@ -64511,6 +65980,7 @@ class MeshToonMaterial extends Material { * A material that maps the normal vectors to RGB colors. * * @augments Material + * @demo scenes/material-browser.html#MeshNormalMaterial */ class MeshNormalMaterial extends Material { @@ -64679,7 +66149,7 @@ class MeshNormalMaterial extends Material { /** * A material for non-shiny surfaces, without specular highlights. * - * The material uses a non-physically based [Lambertian]{@link https://en.wikipedia.org/wiki/Lambertian_reflectance} + * The material uses a non-physically based [Lambertian](https://en.wikipedia.org/wiki/Lambertian_reflectance) * model for calculating reflectance. This can simulate some surfaces (such * as untreated wood or stone) well, but cannot simulate shiny surfaces with * specular highlights (such as varnished wood). `MeshLambertMaterial` uses per-fragment @@ -64691,6 +66161,7 @@ class MeshNormalMaterial extends Material { * {@link MeshPhysicalMaterial}, at the cost of some graphical accuracy. * * @augments Material + * @demo scenes/material-browser.html#MeshLambertMaterial */ class MeshLambertMaterial extends Material { @@ -64938,6 +66409,14 @@ class MeshLambertMaterial extends Material { */ this.reflectivity = 1; + /** + * Scales the effect of the environment map by multiplying its color. + * + * @type {number} + * @default 1 + */ + this.envMapIntensity = 1.0; + /** * The index of refraction (IOR) of air (approximately 1) divided by the * index of refraction of the material. It is used with environment mapping @@ -65044,6 +66523,7 @@ class MeshLambertMaterial extends Material { this.envMapRotation.copy( source.envMapRotation ); this.combine = source.combine; this.reflectivity = source.reflectivity; + this.envMapIntensity = source.envMapIntensity; this.refractionRatio = source.refractionRatio; this.wireframe = source.wireframe; @@ -65071,6 +66551,7 @@ class MeshLambertMaterial extends Material { * shadows. * * @augments Material + * @demo scenes/material-browser.html#MeshMatcapMaterial */ class MeshMatcapMaterial extends Material { @@ -65222,6 +66703,24 @@ class MeshMatcapMaterial extends Material { */ this.alphaMap = null; + /** + * Renders the geometry as a wireframe. + * + * @type {boolean} + * @default false + */ + this.wireframe = false; + + /** + * Controls the thickness of the wireframe. + * + * Can only be used with {@link SVGRenderer}. + * + * @type {number} + * @default 1 + */ + this.wireframeLinewidth = 1; + /** * Whether the material is rendered with flat shading or not. * @@ -65268,6 +66767,9 @@ class MeshMatcapMaterial extends Material { this.alphaMap = source.alphaMap; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.flatShading = source.flatShading; this.fog = source.fog; @@ -65398,7 +66900,9 @@ const Cache = { if ( this.enabled === false ) return; - // console.log( 'THREE.Cache', 'Adding key:', key ); + if ( isBlobURL( key ) ) return; + + // log( 'Cache', 'Adding key:', key ); this.files[ key ] = file; @@ -65415,7 +66919,9 @@ const Cache = { if ( this.enabled === false ) return; - // console.log( 'THREE.Cache', 'Checking key:', key ); + if ( isBlobURL( key ) ) return; + + // log( 'Cache', 'Checking key:', key ); return this.files[ key ]; @@ -65446,6 +66952,31 @@ const Cache = { }; +/** + * Returns true if the given cache key contains the blob: scheme. + * + * @private + * @param {string} key - The cache key. + * @return {boolean} Whether the given cache key contains the blob: scheme or not. + */ +function isBlobURL( key ) { + + try { + + const urlString = key.slice( key.indexOf( ':' ) + 1 ); // remove type identifier + + const url = new URL( urlString ); + return url.protocol === 'blob:'; + + } catch ( e ) { + + // If the string is not a valid URL, it throws an error + return false; + + } + +} + /** * Handles and keeps track of loaded and pending data. A default global * instance of this class is created and used by loaders if not supplied @@ -65520,9 +67051,10 @@ class LoadingManager { /** * Used for aborting ongoing requests in loaders using this manager. * - * @type {AbortController} + * @private + * @type {AbortController | null} */ - this.abortController = new AbortController(); + this._abortController = null; /** * This should be called by any loader using the manager when the loader @@ -65733,8 +67265,9 @@ class LoadingManager { */ this.abort = function () { + this.abortController.abort(); - this.abortController = new AbortController(); + this._abortController = null; return this; @@ -65742,6 +67275,26 @@ class LoadingManager { } + // TODO: Revert this back to a single member variable once this issue has been fixed + // https://github.com/cloudflare/workerd/issues/3657 + + /** + * Used for aborting ongoing requests in loaders using this manager. + * + * @type {AbortController} + */ + get abortController() { + + if ( ! this._abortController ) { + + this._abortController = new AbortController(); + + } + + return this._abortController; + + } + } /** @@ -65806,13 +67359,19 @@ class Loader { this.resourcePath = ''; /** - * The [request header]{@link https://developer.mozilla.org/en-US/docs/Glossary/Request_header} + * The [request header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header) * used in HTTP request. * * @type {Object} */ this.requestHeader = {}; + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); + + } + } /** @@ -65871,7 +67430,7 @@ class Loader { /** * Whether the XMLHttpRequest uses credentials such as cookies, authorization - * headers or TLS client certificates, see [XMLHttpRequest.withCredentials]{@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials}. + * headers or TLS client certificates, see [XMLHttpRequest.withCredentials](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials). * * Note: This setting has no effect if you are loading files locally or from the same domain. * @@ -65914,7 +67473,7 @@ class Loader { /** * Sets the given request header. * - * @param {Object} requestHeader - A [request header]{@link https://developer.mozilla.org/en-US/docs/Glossary/Request_header} + * @param {Object} requestHeader - A [request header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header) * for configuring the HTTP request. * @return {Loader} A reference to this instance. */ @@ -65976,7 +67535,7 @@ const _loading = new WeakMap(); * ``` * Please note that `ImageLoader` has dropped support for progress * events in `r84`. For an `ImageLoader` that supports progress events, see - * [this thread]{@link https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639}. + * [this thread](https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639). * * @augments Loader */ @@ -66139,7 +67698,7 @@ class ImageLoader extends Loader { * ``` * Please note that `TextureLoader` has dropped support for progress * events in `r84`. For a `TextureLoader` that supports progress events, see - * [this thread]{@link https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145}. + * [this thread](https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145). * * @augments Loader */ @@ -66248,7 +67807,7 @@ class Light extends Object3D { */ dispose() { - // Empty here in base class; some subclasses override. + this.dispatchEvent( { type: 'dispose' } ); } @@ -66270,16 +67829,6 @@ class Light extends Object3D { data.object.color = this.color.getHex(); data.object.intensity = this.intensity; - if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); - - if ( this.distance !== undefined ) data.object.distance = this.distance; - if ( this.angle !== undefined ) data.object.angle = this.angle; - if ( this.decay !== undefined ) data.object.decay = this.decay; - if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - - if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); - if ( this.target !== undefined ) data.object.target = this.target.uuid; - return data; } @@ -66345,11 +67894,21 @@ class HemisphereLight extends Light { } + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.groundColor = this.groundColor.getHex(); + + return data; + + } + } -const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); -const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); -const _lookTarget$1 = /*@__PURE__*/ new Vector3(); +const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld = /*@__PURE__*/ new Vector3(); +const _lookTarget = /*@__PURE__*/ new Vector3(); /** * Abstract base class for light shadow classes. These classes @@ -66394,6 +67953,16 @@ class LightShadow { */ this.bias = 0; + /** + * A node version of `bias`. Only supported with `WebGPURenderer`. + * + * If a bias node is defined, `bias` has no effect. + * + * @type {?Node} + * @default null + */ + this.biasNode = null; + /** * Defines how much the position used to query the shadow map is offset along * the object normal. The default is `0`. Increasing this value can be used to @@ -66411,9 +67980,6 @@ class LightShadow { * map size will allow for a higher value to be used here before these effects * become visible. * - * The property has no effect when the shadow map type is `PCFSoftShadowMap` and - * and it is recommended to increase softness by decreasing the shadow map size instead. - * * The property has no effect when the shadow map type is `BasicShadowMap`. * * @type {number} @@ -66538,22 +68104,22 @@ class LightShadow { const shadowCamera = this.camera; const shadowMatrix = this.matrix; - _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld$1 ); + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld ); - _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget$1 ); + _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget ); shadowCamera.updateMatrixWorld(); - _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - this._frustum.setFromProjectionMatrix( _projScreenMatrix$1, shadowCamera.coordinateSystem, shadowCamera.reversedDepth ); + _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix, shadowCamera.coordinateSystem, shadowCamera.reversedDepth ); - if ( shadowCamera.reversedDepth ) { + if ( shadowCamera.coordinateSystem === WebGPUCoordinateSystem || shadowCamera.reversedDepth ) { shadowMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0, 0.0, // Identity Z (preserving the correct [0, 1] range from the projection matrix) 0.0, 0.0, 0.0, 1.0 ); @@ -66568,7 +68134,7 @@ class LightShadow { } - shadowMatrix.multiply( _projScreenMatrix$1 ); + shadowMatrix.multiply( _projScreenMatrix ); } @@ -66637,6 +68203,8 @@ class LightShadow { this.mapSize.copy( source.mapSize ); + this.biasNode = source.biasNode; + return this; } @@ -66782,6 +68350,8 @@ class DirectionalLight extends Light { dispose() { + super.dispose(); + this.shadow.dispose(); } @@ -66797,6 +68367,17 @@ class DirectionalLight extends Light { } + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.shadow = this.shadow.toJSON(); + data.object.target = this.target.uuid; + + return data; + + } + } /** @@ -66873,7 +68454,7 @@ class Raycaster { this.near = near; /** - * All results returned are further away than near. Near can't be negative. + * All results returned are closer than far. Far can't be lower than near. * * @type {number} * @default Infinity @@ -66967,7 +68548,7 @@ class Raycaster { } else { - console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); + error( 'Raycaster: Unsupported camera type: ' + camera.type ); } @@ -67002,7 +68583,7 @@ class Raycaster { * @property {Object3D} object - The 3D object that has been intersected. * @property {Vector2} uv - U,V coordinates at point of intersection. * @property {Vector2} uv1 - Second set of U,V coordinates at point of intersection. - * @property {Vector3} uv1 - Interpolated normal vector at point of intersection. + * @property {Vector3} normal - Interpolated normal vector at point of intersection. * @property {number} instanceId - The index number of the instance where the ray * intersects the {@link InstancedMesh}. */ @@ -67095,135 +68676,191 @@ function intersect( object, raycaster, intersects, recursive ) { } /** - * Class for keeping track of time. + * This class is an alternative to {@link Clock} with a different API design and behavior. + * The goal is to avoid the conceptual flaws that became apparent in `Clock` over time. + * + * - `Timer` has an `update()` method that updates its internal state. That makes it possible to + * call `getDelta()` and `getElapsed()` multiple times per simulation step without getting different values. + * - The class can make use of the Page Visibility API to avoid large time delta values when the app + * is inactive (e.g. tab switched or browser hidden). + * + * ```js + * const timer = new Timer(); + * timer.connect( document ); // use Page Visibility API + * ``` */ -class Clock { +class Timer { /** - * Constructs a new clock. + * Constructs a new timer. + */ + constructor() { + + this._previousTime = 0; + this._currentTime = 0; + this._startTime = performance.now(); + + this._delta = 0; + this._elapsed = 0; + + this._timescale = 1; + + this._document = null; + this._pageVisibilityHandler = null; + + } + + /** + * Connect the timer to the given document.Calling this method is not mandatory to + * use the timer but enables the usage of the Page Visibility API to avoid large time + * delta values. * - * @param {boolean} [autoStart=true] - Whether to automatically start the clock when - * `getDelta()` is called for the first time. + * @param {Document} document - The document. */ - constructor( autoStart = true ) { + connect( document ) { - /** - * If set to `true`, the clock starts automatically when `getDelta()` is called - * for the first time. - * - * @type {boolean} - * @default true - */ - this.autoStart = autoStart; + this._document = document; - /** - * Holds the time at which the clock's `start()` method was last called. - * - * @type {number} - * @default 0 - */ - this.startTime = 0; + // use Page Visibility API to avoid large time delta values - /** - * Holds the time at which the clock's `start()`, `getElapsedTime()` or - * `getDelta()` methods were last called. - * - * @type {number} - * @default 0 - */ - this.oldTime = 0; + if ( document.hidden !== undefined ) { - /** - * Keeps track of the total time that the clock has been running. - * - * @type {number} - * @default 0 - */ - this.elapsedTime = 0; + this._pageVisibilityHandler = handleVisibilityChange.bind( this ); - /** - * Whether the clock is running or not. - * - * @type {boolean} - * @default true - */ - this.running = false; + document.addEventListener( 'visibilitychange', this._pageVisibilityHandler, false ); + + } } /** - * Starts the clock. When `autoStart` is set to `true`, the method is automatically - * called by the class. + * Disconnects the timer from the DOM and also disables the usage of the Page Visibility API. */ - start() { + disconnect() { + + if ( this._pageVisibilityHandler !== null ) { - this.startTime = performance.now(); + this._document.removeEventListener( 'visibilitychange', this._pageVisibilityHandler ); + this._pageVisibilityHandler = null; - this.oldTime = this.startTime; - this.elapsedTime = 0; - this.running = true; + } + + this._document = null; } /** - * Stops the clock. + * Returns the time delta in seconds. + * + * @return {number} The time delta in second. */ - stop() { + getDelta() { - this.getElapsedTime(); - this.running = false; - this.autoStart = false; + return this._delta / 1000; } /** * Returns the elapsed time in seconds. * - * @return {number} The elapsed time. + * @return {number} The elapsed time in second. */ - getElapsedTime() { + getElapsed() { - this.getDelta(); - return this.elapsedTime; + return this._elapsed / 1000; } /** - * Returns the delta time in seconds. + * Returns the timescale. * - * @return {number} The delta time. + * @return {number} The timescale. */ - getDelta() { + getTimescale() { - let diff = 0; + return this._timescale; - if ( this.autoStart && ! this.running ) { + } - this.start(); - return 0; + /** + * Sets the given timescale which scale the time delta computation + * in `update()`. + * + * @param {number} timescale - The timescale to set. + * @return {Timer} A reference to this timer. + */ + setTimescale( timescale ) { - } + this._timescale = timescale; + + return this; + + } + + /** + * Resets the time computation for the current simulation step. + * + * @return {Timer} A reference to this timer. + */ + reset() { - if ( this.running ) { + this._currentTime = performance.now() - this._startTime; - const newTime = performance.now(); + return this; - diff = ( newTime - this.oldTime ) / 1000; - this.oldTime = newTime; + } - this.elapsedTime += diff; + /** + * Can be used to free all internal resources. Usually called when + * the timer instance isn't required anymore. + */ + dispose() { + + this.disconnect(); + + } + + /** + * Updates the internal state of the timer. This method should be called + * once per simulation step and before you perform queries against the timer + * (e.g. via `getDelta()`). + * + * @param {number} timestamp - The current time in milliseconds. Can be obtained + * from the `requestAnimationFrame` callback argument. If not provided, the current + * time will be determined with `performance.now`. + * @return {Timer} A reference to this timer. + */ + update( timestamp ) { + + if ( this._pageVisibilityHandler !== null && this._document.hidden === true ) { + + this._delta = 0; + + } else { + + this._previousTime = this._currentTime; + this._currentTime = ( timestamp !== undefined ? timestamp : performance.now() ) - this._startTime; + + this._delta = ( this._currentTime - this._previousTime ) * this._timescale; + this._elapsed += this._delta; // _elapsed is the accumulation of all previous deltas } - return diff; + return this; } } +function handleVisibilityChange() { + + if ( this._document.hidden === false ) this.reset(); + +} + /** * This class can be used to represent points in 3D space as - * [Spherical coordinates]{@link https://en.wikipedia.org/wiki/Spherical_coordinate_system}. + * [Spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system). */ class Spherical { @@ -68026,12 +69663,10 @@ class Line3 { } - c1.copy( p1 ).add( _d1.multiplyScalar( s ) ); - c2.copy( p2 ).add( _d2.multiplyScalar( t ) ); + c1.copy( p1 ).addScaledVector( _d1, s ); + c2.copy( p2 ).addScaledVector( _d2, t ); - c1.sub( c2 ); - - return c1.dot( c1 ); + return c1.distanceToSquared( c2 ); } @@ -68396,7 +70031,7 @@ class ShapePath { let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); holesFirst = isCCW ? ! holesFirst : holesFirst; - // console.log("Holes first", holesFirst); + // log("Holes first", holesFirst); const betterShapeHoles = []; const newShapes = []; @@ -68424,13 +70059,13 @@ class ShapePath { if ( holesFirst ) mainIdx ++; newShapeHoles[ mainIdx ] = []; - //console.log('cw', i); + //log('cw', i); } else { newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); - //console.log('ccw', i); + //log('ccw', i); } @@ -68515,7 +70150,7 @@ class ShapePath { } - //console.log("shape", shapes); + //log("shape", shapes); return shapes; @@ -68535,7 +70170,7 @@ class Controls extends EventDispatcher { * Constructs a new controls instance. * * @param {Object3D} object - The object that is managed by the controls. - * @param {?HTMLDOMElement} domElement - The HTML element used for event listeners. + * @param {?HTMLElement} domElement - The HTML element used for event listeners. */ constructor( object, domElement = null ) { @@ -68551,7 +70186,7 @@ class Controls extends EventDispatcher { /** * The HTML element used for event listeners. * - * @type {?HTMLDOMElement} + * @type {?HTMLElement} * @default null */ this.domElement = domElement; @@ -68601,13 +70236,13 @@ class Controls extends EventDispatcher { * Connects the controls to the DOM. This method has so called "side effects" since * it adds the module's event listeners to the DOM. * - * @param {HTMLDOMElement} element - The DOM element to connect to. + * @param {HTMLElement} element - The DOM element to connect to. */ connect( element ) { if ( element === undefined ) { - console.warn( 'THREE.Controls: connect() now requires an element.' ); // @deprecated, the warning can be removed with r185 + warn( 'Controls: connect() now requires an element.' ); // @deprecated, the warning can be removed with r185 return; } @@ -68677,7 +70312,7 @@ if ( typeof window !== 'undefined' ) { * * See the {@link FontLoader} page for additional details. * - * `TextGeometry` uses [typeface.json]{@link http://gero3.github.io/facetype.js/} generated fonts. + * `TextGeometry` uses [typeface.json](http://gero3.github.io/facetype.js/) generated fonts. * Some existing fonts can be found located in `/examples/fonts`. * * ```js @@ -68712,7 +70347,7 @@ class TextGeometry extends ExtrudeGeometry { } else { - const shapes = font.generateShapes( text, parameters.size ); + const shapes = font.generateShapes( text, parameters.size, parameters.direction ); // defaults @@ -68769,12 +70404,13 @@ class Font { * * @param {string} text - The text. * @param {number} [size=100] - The text size. + * @param {string} [direction='ltr'] - Char direction: ltr(left to right), rtl(right to left) & tb(top bottom). * @return {Array} An array of shapes representing the text. */ - generateShapes( text, size = 100 ) { + generateShapes( text, size = 100, direction = 'ltr' ) { const shapes = []; - const paths = createPaths( text, size, this.data ); + const paths = createPaths( text, size, this.data, direction ); for ( let p = 0, pl = paths.length; p < pl; p ++ ) { @@ -68788,7 +70424,7 @@ class Font { } -function createPaths( text, size, data ) { +function createPaths( text, size, data, direction ) { const chars = Array.from( text ); const scale = size / data.resolution; @@ -68798,6 +70434,12 @@ function createPaths( text, size, data ) { let offsetX = 0, offsetY = 0; + if ( direction == 'rtl' || direction == 'tb' ) { + + chars.reverse(); + + } + for ( let i = 0; i < chars.length; i ++ ) { const char = chars[ i ]; @@ -68810,7 +70452,18 @@ function createPaths( text, size, data ) { } else { const ret = createPath( char, scale, offsetX, offsetY, data ); - offsetX += ret.offsetX; + + if ( direction == 'tb' ) { + + offsetX = 0; + offsetY += data.ascender * scale; + + } else { + + offsetX += ret.offsetX; + + } + paths.push( ret.path ); } @@ -68979,7 +70632,7 @@ class OrbitControls extends Controls { * Constructs a new controls instance. * * @param {Object3D} object - The object that is managed by the controls. - * @param {?HTMLDOMElement} domElement - The HTML element used for event listeners. + * @param {?HTMLElement} domElement - The HTML element used for event listeners. */ constructor( object, domElement = null ) { @@ -69279,6 +70932,8 @@ class OrbitControls extends Controls { */ this.zoom0 = this.object.zoom; + this._cursorStyle = 'auto'; + // the target DOM element for key events this._domElementKeyEvents = null; @@ -69350,6 +71005,34 @@ class OrbitControls extends Controls { } + /** + * Defines the visual representation of the cursor. + * + * @type {('auto'|'grab')} + * @default 'auto' + */ + set cursorStyle( type ) { + + this._cursorStyle = type; + + if ( type === 'grab' ) { + + this.domElement.style.cursor = 'grab'; + + } else { + + this.domElement.style.cursor = 'auto'; + + } + + } + + get cursorStyle() { + + return this._cursorStyle; + + } + connect( element ) { super.connect( element ); @@ -69370,8 +71053,8 @@ class OrbitControls extends Controls { disconnect() { this.domElement.removeEventListener( 'pointerdown', this._onPointerDown ); - this.domElement.removeEventListener( 'pointermove', this._onPointerMove ); - this.domElement.removeEventListener( 'pointerup', this._onPointerUp ); + this.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove ); + this.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp ); this.domElement.removeEventListener( 'pointercancel', this._onPointerUp ); this.domElement.removeEventListener( 'wheel', this._onMouseWheel ); @@ -69429,7 +71112,7 @@ class OrbitControls extends Controls { * Adds key event listeners to the given DOM element. * `window` is a recommended argument for using this method. * - * @param {HTMLDOMElement} domElement - The DOM element + * @param {HTMLElement} domElement - The DOM element */ listenToKeyEvents( domElement ) { @@ -69482,6 +71165,67 @@ class OrbitControls extends Controls { } + /** + * Programmatically pan the camera. + * + * @param {number} deltaX - The horizontal pan amount in pixels. + * @param {number} deltaY - The vertical pan amount in pixels. + */ + pan( deltaX, deltaY ) { + + this._pan( deltaX, deltaY ); + this.update(); + + } + + /** + * Programmatically dolly in (zoom in for perspective camera). + * + * @param {number} dollyScale - The dolly scale factor. + */ + dollyIn( dollyScale ) { + + this._dollyIn( dollyScale ); + this.update(); + + } + + /** + * Programmatically dolly out (zoom out for perspective camera). + * + * @param {number} dollyScale - The dolly scale factor. + */ + dollyOut( dollyScale ) { + + this._dollyOut( dollyScale ); + this.update(); + + } + + /** + * Programmatically rotate the camera left (around the vertical axis). + * + * @param {number} angle - The rotation angle in radians. + */ + rotateLeft( angle ) { + + this._rotateLeft( angle ); + this.update(); + + } + + /** + * Programmatically rotate the camera up (around the horizontal axis). + * + * @param {number} angle - The rotation angle in radians. + */ + rotateUp( angle ) { + + this._rotateUp( angle ); + this.update(); + + } + update( deltaTime = null ) { const position = this.object.position; @@ -70346,8 +72090,8 @@ function onPointerDown( event ) { this.domElement.setPointerCapture( event.pointerId ); - this.domElement.addEventListener( 'pointermove', this._onPointerMove ); - this.domElement.addEventListener( 'pointerup', this._onPointerUp ); + this.domElement.ownerDocument.addEventListener( 'pointermove', this._onPointerMove ); + this.domElement.ownerDocument.addEventListener( 'pointerup', this._onPointerUp ); } @@ -70369,6 +72113,12 @@ function onPointerDown( event ) { } + if ( this._cursorStyle === 'grab' ) { + + this.domElement.style.cursor = 'grabbing'; + + } + } function onPointerMove( event ) { @@ -70397,13 +72147,19 @@ function onPointerUp( event ) { this.domElement.releasePointerCapture( event.pointerId ); - this.domElement.removeEventListener( 'pointermove', this._onPointerMove ); - this.domElement.removeEventListener( 'pointerup', this._onPointerUp ); + this.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove ); + this.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp ); this.dispatchEvent( _endEvent ); this.state = _STATE.NONE; + if ( this._cursorStyle === 'grab' ) { + + this.domElement.style.cursor = 'grab'; + + } + break; case 1: @@ -71411,12 +73167,12 @@ class EffectComposer { this.copyPass.material.blending = NoBlending; /** - * The internal clock for managing time data. + * The internal timer for managing time data. * * @private - * @type {Clock} + * @type {Timer} */ - this.clock = new Clock(); + this.timer = new Timer(); } @@ -71505,9 +73261,11 @@ class EffectComposer { // deltaTime value is in seconds + this.timer.update(); + if ( deltaTime === undefined ) { - deltaTime = this.clock.getDelta(); + deltaTime = this.timer.getDelta(); } @@ -71740,6 +73498,16 @@ class RenderPass extends Pass { * @default false */ this.needsSwap = false; + + /** + * This flag indicates that this pass renders the scene itself. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isRenderPass = true; + this._oldClearColor = new Color(); } @@ -71897,7 +73665,7 @@ const LuminosityHighPassShader = { * When using this pass, tone mapping must be enabled in the renderer settings. * * Reference: - * - [Bloom in Unreal Engine]{@link https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/} + * - [Bloom in Unreal Engine](https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/) * * ```js * const resolution = new THREE.Vector2( window.innerWidth, window.innerHeight ); @@ -71931,7 +73699,7 @@ class UnrealBloomPass extends Pass { this.strength = strength; /** - * The Bloom radius. + * The Bloom radius. Must be in the range `[0,1]`. * * @type {number} */ @@ -72020,7 +73788,9 @@ class UnrealBloomPass extends Pass { // gaussian blur materials this.separableBlurMaterials = []; - const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; + // These sizes have been changed to account for the altered coefficients-calculation to avoid blockiness, + // while retaining the same blur-strength. For details see https://github.com/mrdoob/three.js/pull/31528 + const kernelSizeArray = [ 6, 10, 14, 18, 22 ]; resx = Math.round( this.resolution.x / 2 ); resy = Math.round( this.resolution.y / 2 ); @@ -72060,6 +73830,7 @@ class UnrealBloomPass extends Pass { uniforms: this.copyUniforms, vertexShader: CopyShader.vertexShader, fragmentShader: CopyShader.fragmentShader, + premultipliedAlpha: true, blending: AdditiveBlending, depthTest: false, depthWrite: false, @@ -72251,10 +74022,11 @@ class UnrealBloomPass extends Pass { _getSeparableBlurMaterial( kernelRadius ) { const coefficients = []; + const sigma = kernelRadius / 3; for ( let i = 0; i < kernelRadius; i ++ ) { - coefficients.push( 0.39894 * Math.exp( -0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); + coefficients.push( 0.39894 * Math.exp( -0.5 * i * i / ( sigma * sigma ) ) / sigma ); } @@ -72271,34 +74043,46 @@ class UnrealBloomPass extends Pass { 'gaussianCoefficients': { value: coefficients } // precomputed Gaussian coefficients }, - vertexShader: - `varying vec2 vUv; + vertexShader: /* glsl */` + + varying vec2 vUv; + void main() { + vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, - fragmentShader: - `#include + fragmentShader: /* glsl */` + + #include + varying vec2 vUv; + uniform sampler2D colorTexture; uniform vec2 invSize; uniform vec2 direction; uniform float gaussianCoefficients[KERNEL_RADIUS]; void main() { + float weightSum = gaussianCoefficients[0]; vec3 diffuseSum = texture2D( colorTexture, vUv ).rgb * weightSum; - for( int i = 1; i < KERNEL_RADIUS; i ++ ) { - float x = float(i); + + for ( int i = 1; i < KERNEL_RADIUS; i ++ ) { + + float x = float( i ); float w = gaussianCoefficients[i]; vec2 uvOffset = direction * invSize * x; vec3 sample1 = texture2D( colorTexture, vUv + uvOffset ).rgb; vec3 sample2 = texture2D( colorTexture, vUv - uvOffset ).rgb; - diffuseSum += (sample1 + sample2) * w; - weightSum += 2.0 * w; + diffuseSum += ( sample1 + sample2 ) * w; + } - gl_FragColor = vec4(diffuseSum/weightSum, 1.0); + + gl_FragColor = vec4( diffuseSum, 1.0 ); + }` } ); @@ -72324,15 +74108,21 @@ class UnrealBloomPass extends Pass { 'bloomRadius': { value: 0.0 } }, - vertexShader: - `varying vec2 vUv; + vertexShader: /* glsl */` + + varying vec2 vUv; + void main() { + vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, - fragmentShader: - `varying vec2 vUv; + fragmentShader: /* glsl */` + + varying vec2 vUv; + uniform sampler2D blurTexture1; uniform sampler2D blurTexture2; uniform sampler2D blurTexture3; @@ -72343,17 +74133,27 @@ class UnrealBloomPass extends Pass { uniform float bloomFactors[NUM_MIPS]; uniform vec3 bloomTintColors[NUM_MIPS]; - float lerpBloomFactor(const in float factor) { + float lerpBloomFactor( const in float factor ) { + float mirrorFactor = 1.2 - factor; - return mix(factor, mirrorFactor, bloomRadius); + return mix( factor, mirrorFactor, bloomRadius ); + } void main() { - gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) + - lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) + - lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) + - lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) + - lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) ); + + // 3.0 for backwards compatibility with previous alpha-based intensity + vec3 bloom = 3.0 * bloomStrength * ( + lerpBloomFactor( bloomFactors[ 0 ] ) * bloomTintColors[ 0 ] * texture2D( blurTexture1, vUv ).rgb + + lerpBloomFactor( bloomFactors[ 1 ] ) * bloomTintColors[ 1 ] * texture2D( blurTexture2, vUv ).rgb + + lerpBloomFactor( bloomFactors[ 2 ] ) * bloomTintColors[ 2 ] * texture2D( blurTexture3, vUv ).rgb + + lerpBloomFactor( bloomFactors[ 3 ] ) * bloomTintColors[ 3 ] * texture2D( blurTexture4, vUv ).rgb + + lerpBloomFactor( bloomFactors[ 4 ] ) * bloomTintColors[ 4 ] * texture2D( blurTexture5, vUv ).rgb + ); + + float bloomAlpha = max( bloom.r, max( bloom.g, bloom.b ) ); + gl_FragColor = vec4( bloom, bloomAlpha ); + }` } ); @@ -72493,7 +74293,7 @@ class Projector { _face, _faceCount, _facePoolLength = 0, _line, _lineCount, _linePoolLength = 0, _sprite, _spriteCount, _spritePoolLength = 0, - _modelMatrix; + _modelMatrix, _clipInput = [], _clipOutput = []; const @@ -72513,7 +74313,19 @@ class Projector { _frustum = new Frustum(), - _objectPool = [], _vertexPool = [], _facePool = [], _linePool = [], _spritePool = []; + _objectPool = [], _vertexPool = [], _facePool = [], _linePool = [], _spritePool = [], + + _clipVertexPool = [], + _clipPos1 = new Vector4(), + _clipPos2 = new Vector4(), + _clipPos3 = new Vector4(), + _screenVertexPool = [], + _clipInputVertices = [ null, null, null ], + + _clipPlanes = [ + { sign: 1 }, + { sign: -1 } + ]; // @@ -72652,48 +74464,165 @@ class Projector { const v2 = _vertexPool[ b ]; const v3 = _vertexPool[ c ]; - if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return; + // Get homogeneous clip space positions (before perspective divide) + _clipPos1.copy( v1.positionWorld ).applyMatrix4( _viewProjectionMatrix ); + _clipPos2.copy( v2.positionWorld ).applyMatrix4( _viewProjectionMatrix ); + _clipPos3.copy( v3.positionWorld ).applyMatrix4( _viewProjectionMatrix ); + + // Check if triangle needs clipping + const nearDist1 = _clipPos1.z + _clipPos1.w; + const nearDist2 = _clipPos2.z + _clipPos2.w; + const nearDist3 = _clipPos3.z + _clipPos3.w; + const farDist1 = - _clipPos1.z + _clipPos1.w; + const farDist2 = - _clipPos2.z + _clipPos2.w; + const farDist3 = - _clipPos3.z + _clipPos3.w; + + // Check if completely outside + if ( ( nearDist1 < 0 && nearDist2 < 0 && nearDist3 < 0 ) || + ( farDist1 < 0 && farDist2 < 0 && farDist3 < 0 ) ) { + + return; // Triangle completely clipped + + } + + // Check if completely inside (no clipping needed) + if ( nearDist1 >= 0 && nearDist2 >= 0 && nearDist3 >= 0 && + farDist1 >= 0 && farDist2 >= 0 && farDist3 >= 0 ) { - if ( material.side === DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) { + // No clipping needed - use original path + if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return; - _face = getNextFaceInPool(); + if ( material.side === DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) { - _face.id = object.id; - _face.v1.copy( v1 ); - _face.v2.copy( v2 ); - _face.v3.copy( v3 ); - _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3; - _face.renderOrder = object.renderOrder; + _face = getNextFaceInPool(); - // face normal - _vector3.subVectors( v3.position, v2.position ); - _vector4.subVectors( v1.position, v2.position ); - _vector3.cross( _vector4 ); - _face.normalModel.copy( _vector3 ); - _face.normalModel.applyMatrix3( normalMatrix ).normalize(); + _face.id = object.id; + _face.v1.copy( v1 ); + _face.v2.copy( v2 ); + _face.v3.copy( v3 ); + _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3; + _face.renderOrder = object.renderOrder; - for ( let i = 0; i < 3; i ++ ) { + // face normal + _vector3.subVectors( v3.position, v2.position ); + _vector4.subVectors( v1.position, v2.position ); + _vector3.cross( _vector4 ); + _face.normalModel.copy( _vector3 ); + _face.normalModel.applyMatrix3( normalMatrix ).normalize(); - const normal = _face.vertexNormalsModel[ i ]; - normal.fromArray( normals, arguments[ i ] * 3 ); - normal.applyMatrix3( normalMatrix ).normalize(); + for ( let i = 0; i < 3; i ++ ) { - const uv = _face.uvs[ i ]; - uv.fromArray( uvs, arguments[ i ] * 2 ); + const normal = _face.vertexNormalsModel[ i ]; + normal.fromArray( normals, arguments[ i ] * 3 ); + normal.applyMatrix3( normalMatrix ).normalize(); + + const uv = _face.uvs[ i ]; + uv.fromArray( uvs, arguments[ i ] * 2 ); + + } + + _face.vertexNormalsLength = 3; + + _face.material = material; + + if ( material.vertexColors ) { + + _face.color.fromArray( colors, a * 3 ); + + } + + _renderData.elements.push( _face ); } - _face.vertexNormalsLength = 3; + return; + + } + + // Triangle needs clipping + _clipInputVertices[ 0 ] = _clipPos1; + _clipInputVertices[ 1 ] = _clipPos2; + _clipInputVertices[ 2 ] = _clipPos3; + const clippedCount = clipTriangle( _clipInputVertices ); + + if ( clippedCount < 3 ) return; // Triangle completely clipped + + // Perform perspective divide on clipped vertices and create screen vertices + for ( let i = 0; i < clippedCount; i ++ ) { - _face.material = material; + const cv = _clipInput[ i ]; - if ( material.vertexColors ) { + // Get or create renderable vertex from pool + let sv = _screenVertexPool[ i ]; + if ( ! sv ) { - _face.color.fromArray( colors, a * 3 ); + sv = new RenderableVertex(); + _screenVertexPool[ i ] = sv; } - _renderData.elements.push( _face ); + // Perform perspective divide + const invW = 1 / cv.w; + sv.positionScreen.set( cv.x * invW, cv.y * invW, cv.z * invW, 1 ); + + // Interpolate world position (simplified - using weighted average based on barycentric-like coords) + // For a proper implementation, we'd need to track interpolation weights + sv.positionWorld.copy( v1.positionWorld ); + + sv.visible = true; + + } + + // Triangulate the clipped polygon (simple fan triangulation) + for ( let i = 1; i < clippedCount - 1; i ++ ) { + + const tv1 = _screenVertexPool[ 0 ]; + const tv2 = _screenVertexPool[ i ]; + const tv3 = _screenVertexPool[ i + 1 ]; + + if ( material.side === DoubleSide || checkBackfaceCulling( tv1, tv2, tv3 ) === true ) { + + _face = getNextFaceInPool(); + + _face.id = object.id; + _face.v1.copy( tv1 ); + _face.v2.copy( tv2 ); + _face.v3.copy( tv3 ); + _face.z = ( tv1.positionScreen.z + tv2.positionScreen.z + tv3.positionScreen.z ) / 3; + _face.renderOrder = object.renderOrder; + + // face normal - use original triangle's normal + _vector3.subVectors( v3.position, v2.position ); + _vector4.subVectors( v1.position, v2.position ); + _vector3.cross( _vector4 ); + _face.normalModel.copy( _vector3 ); + _face.normalModel.applyMatrix3( normalMatrix ).normalize(); + + // Use original vertex normals and UVs (simplified - proper impl would interpolate) + for ( let j = 0; j < 3; j ++ ) { + + const normal = _face.vertexNormalsModel[ j ]; + normal.fromArray( normals, arguments[ j ] * 3 ); + normal.applyMatrix3( normalMatrix ).normalize(); + + const uv = _face.uvs[ j ]; + uv.fromArray( uvs, arguments[ j ] * 2 ); + + } + + _face.vertexNormalsLength = 3; + + _face.material = material; + + if ( material.vertexColors ) { + + _face.color.fromArray( colors, a * 3 ); + + } + + _renderData.elements.push( _face ); + + } } @@ -72802,7 +74731,7 @@ class Projector { if ( sortObjects === true ) { - _renderData.objects.sort( painterSort ); + painterSortStable( _renderData.objects, 0, _renderData.objects.length ); } @@ -73068,7 +74997,7 @@ class Projector { if ( sortElements === true ) { - _renderData.elements.sort( painterSort ); + painterSortStable( _renderData.elements, 0, _renderData.elements.length ); } @@ -73212,6 +75141,115 @@ class Projector { } + function painterSortStable( array, start, length ) { + + // A stable insertion sort for sorting render items + // This avoids the GC overhead of Array.prototype.sort() + + for ( let i = start + 1; i < start + length; i ++ ) { + + const item = array[ i ]; + let j = i - 1; + + while ( j >= start && painterSort( array[ j ], item ) > 0 ) { + + array[ j + 1 ] = array[ j ]; + j --; + + } + + array[ j + 1 ] = item; + + } + + } + + // Sutherland-Hodgman triangle clipping in homogeneous clip space + // Returns count of vertices in clipped polygon (0 if completely clipped, 3+ if partially clipped) + // Result vertices are in _clipInput array + function clipTriangle( vertices ) { + + // Initialize input with the three input vertices + _clipInput[ 0 ] = vertices[ 0 ]; + _clipInput[ 1 ] = vertices[ 1 ]; + _clipInput[ 2 ] = vertices[ 2 ]; + + let inputCount = 3; + let outputCount = 0; + + for ( let p = 0; p < _clipPlanes.length; p ++ ) { + + const plane = _clipPlanes[ p ]; + outputCount = 0; + + if ( inputCount === 0 ) break; + + for ( let i = 0; i < inputCount; i ++ ) { + + const v1 = _clipInput[ i ]; + const v2 = _clipInput[ ( i + 1 ) % inputCount ]; + + const d1 = plane.sign * v1.z + v1.w; + const d2 = plane.sign * v2.z + v2.w; + + const v1Inside = d1 >= 0; + const v2Inside = d2 >= 0; + + if ( v1Inside && v2Inside ) { + + // Both inside - add v1 + _clipOutput[ outputCount ++ ] = v1; + + } else if ( v1Inside && ! v2Inside ) { + + // v1 inside, v2 outside - add v1 and intersection + _clipOutput[ outputCount ++ ] = v1; + + const t = d1 / ( d1 - d2 ); + let intersection = _clipVertexPool[ outputCount ]; + if ( ! intersection ) { + + intersection = new Vector4(); + _clipVertexPool[ outputCount ] = intersection; + + } + + intersection.lerpVectors( v1, v2, t ); + _clipOutput[ outputCount ++ ] = intersection; + + } else if ( ! v1Inside && v2Inside ) { + + // v1 outside, v2 inside - add intersection only + const t = d1 / ( d1 - d2 ); + let intersection = _clipVertexPool[ outputCount ]; + if ( ! intersection ) { + + intersection = new Vector4(); + _clipVertexPool[ outputCount ] = intersection; + + } + + intersection.lerpVectors( v1, v2, t ); + _clipOutput[ outputCount ++ ] = intersection; + + } + + // Both outside - add nothing + + } + + // Swap input/output + const temp = _clipInput; + _clipInput = _clipOutput; + _clipOutput = temp; + inputCount = outputCount; + + } + + return inputCount; + + } + function clipLine( s1, s2 ) { let alpha1 = 0, alpha2 = 1; @@ -73322,6 +75360,8 @@ class SVGRenderer { _svgNode, _pathCount = 0, + _svgObjectCount = 0, + _renderListCount = 0, _precision = null, _quality = 1, @@ -73348,6 +75388,8 @@ class SVGRenderer { _viewProjectionMatrix = new Matrix4(), _svgPathPool = [], + _svgObjectsPool = [], + _renderListPool = [], _projector = new Projector(), _svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ); @@ -73355,7 +75397,7 @@ class SVGRenderer { /** * The DOM where the renderer appends its child-elements. * - * @type {DOMElement} + * @type {SVGSVGElement} */ this.domElement = _svg; @@ -73418,8 +75460,8 @@ class SVGRenderer { }; /** - * Sets the render quality. Setting to `high` means This value indicates that the browser - * tries to improve the SVG quality over rendering speed and geometric precision. + * Sets the render quality. Setting to `high` makes the browser improve SVG quality + * over rendering speed and geometric precision. * * @param {('low'|'high')} quality - The quality. */ @@ -73510,6 +75552,49 @@ class SVGRenderer { } + function renderSort( a, b ) { + + const aOrder = a.data.renderOrder !== undefined ? a.data.renderOrder : 0; + const bOrder = b.data.renderOrder !== undefined ? b.data.renderOrder : 0; + + if ( aOrder !== bOrder ) { + + return aOrder - bOrder; + + } else { + + const aZ = a.data.z !== undefined ? a.data.z : 0; + const bZ = b.data.z !== undefined ? b.data.z : 0; + + return bZ - aZ; // Painter's algorithm: far to near + + } + + } + + function arraySortStable( array, start, length ) { + + // A stable insertion sort for sorting the render list + // This avoids the GC overhead of Array.prototype.sort() + + for ( let i = start + 1; i < start + length; i ++ ) { + + const item = array[ i ]; + let j = i - 1; + + while ( j >= start && renderSort( array[ j ], item ) > 0 ) { + + array[ j + 1 ] = array[ j ]; + j --; + + } + + array[ j + 1 ] = item; + + } + + } + /** * Performs a manual clear with the defined clear color. */ @@ -73562,10 +75647,7 @@ class SVGRenderer { calculateLights( _lights ); - // reset accumulated path - - _currentPath = ''; - _currentStyle = ''; + _renderListCount = 0; for ( let e = 0, el = _elements.length; e < el; e ++ ) { @@ -73574,88 +75656,126 @@ class SVGRenderer { if ( material === undefined || material.opacity === 0 ) continue; - _elemBox.makeEmpty(); + getRenderItem( _renderListCount ++, 'element', element, material ); + + } + + _svgObjectCount = 0; + + scene.traverseVisible( function ( object ) { + + if ( object.isSVGObject ) { - if ( element instanceof RenderableSprite ) { + _vector3.setFromMatrixPosition( object.matrixWorld ); + _vector3.applyMatrix4( _viewProjectionMatrix ); - _v1 = element; - _v1.x *= _svgWidthHalf; _v1.y *= - _svgHeightHalf; + if ( _vector3.z < -1 || _vector3.z > 1 ) return; - renderSprite( _v1, element, material ); + const x = _vector3.x * _svgWidthHalf; + const y = - _vector3.y * _svgHeightHalf; - } else if ( element instanceof RenderableLine ) { + const svgObject = getSVGObjectData( _svgObjectCount ++ ); - _v1 = element.v1; _v2 = element.v2; + svgObject.node = object.node; + svgObject.x = x; + svgObject.y = y; + svgObject.z = _vector3.z; + svgObject.renderOrder = object.renderOrder; - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; + getRenderItem( _renderListCount ++, 'svgObject', svgObject, null ); - _elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen ] ); + } - if ( _clipBox.intersectsBox( _elemBox ) === true ) { + } ); - renderLine( _v1, _v2, material ); + if ( this.sortElements ) { - } + arraySortStable( _renderListPool, 0, _renderListCount ); - } else if ( element instanceof RenderableFace ) { + } - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; + // Reset accumulated path + _currentPath = ''; + _currentStyle = ''; - if ( _v1.positionScreen.z < -1 || _v1.positionScreen.z > 1 ) continue; - if ( _v2.positionScreen.z < -1 || _v2.positionScreen.z > 1 ) continue; - if ( _v3.positionScreen.z < -1 || _v3.positionScreen.z > 1 ) continue; + // Render in sorted order + for ( let i = 0; i < _renderListCount; i ++ ) { - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; - _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf; + const item = _renderListPool[ i ]; - if ( this.overdraw > 0 ) { + if ( item.type === 'svgObject' ) { - expand( _v1.positionScreen, _v2.positionScreen, this.overdraw ); - expand( _v2.positionScreen, _v3.positionScreen, this.overdraw ); - expand( _v3.positionScreen, _v1.positionScreen, this.overdraw ); + flushPath(); // Flush any accumulated paths before inserting SVG node - } + const svgObject = item.data; + const node = svgObject.node; + node.setAttribute( 'transform', 'translate(' + svgObject.x + ',' + svgObject.y + ')' ); + _svg.appendChild( node ); - _elemBox.setFromPoints( [ - _v1.positionScreen, - _v2.positionScreen, - _v3.positionScreen - ] ); + } else { - if ( _clipBox.intersectsBox( _elemBox ) === true ) { + const element = item.data; + const material = item.material; - renderFace3( _v1, _v2, _v3, element, material ); + _elemBox.makeEmpty(); - } + if ( element instanceof RenderableSprite ) { - } + _v1 = element; + _v1.x *= _svgWidthHalf; _v1.y *= - _svgHeightHalf; - } + renderSprite( _v1, element, material ); - flushPath(); // just to flush last svg:path + } else if ( element instanceof RenderableLine ) { - scene.traverseVisible( function ( object ) { + _v1 = element.v1; _v2 = element.v2; - if ( object.isSVGObject ) { + _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; + _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; - _vector3.setFromMatrixPosition( object.matrixWorld ); - _vector3.applyMatrix4( _viewProjectionMatrix ); + _elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen ] ); - if ( _vector3.z < -1 || _vector3.z > 1 ) return; + if ( _clipBox.intersectsBox( _elemBox ) === true ) { - const x = _vector3.x * _svgWidthHalf; - const y = - _vector3.y * _svgHeightHalf; + renderLine( _v1, _v2, material ); + + } - const node = object.node; - node.setAttribute( 'transform', 'translate(' + x + ',' + y + ')' ); + } else if ( element instanceof RenderableFace ) { - _svg.appendChild( node ); + _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; + + _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; + _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; + _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf; + + if ( this.overdraw > 0 ) { + + expand( _v1.positionScreen, _v2.positionScreen, this.overdraw ); + expand( _v2.positionScreen, _v3.positionScreen, this.overdraw ); + expand( _v3.positionScreen, _v1.positionScreen, this.overdraw ); + + } + + _elemBox.setFromPoints( [ + _v1.positionScreen, + _v2.positionScreen, + _v3.positionScreen + ] ); + + if ( _clipBox.intersectsBox( _elemBox ) === true ) { + + renderFace3( _v1, _v2, _v3, element, material ); + + } + + } } - } ); + } + + flushPath(); // Flush any remaining paths }; @@ -73895,21 +76015,71 @@ class SVGRenderer { function getPathNode( id ) { - if ( _svgPathPool[ id ] == null ) { + let path = _svgPathPool[ id ]; - _svgPathPool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); + if ( path === undefined ) { + + path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); if ( _quality == 0 ) { - _svgPathPool[ id ].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed + path.setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed } - return _svgPathPool[ id ]; + _svgPathPool[ id ] = path; } - return _svgPathPool[ id ]; + return path; + + } + + function getSVGObjectData( id ) { + + let svgObject = _svgObjectsPool[ id ]; + + if ( svgObject === undefined ) { + + svgObject = { + node: null, + x: 0, + y: 0, + z: 0, + renderOrder: 0 + }; + + _svgObjectsPool[ id ] = svgObject; + + } + + return svgObject; + + } + + function getRenderItem( id, type, data, material ) { + + let item = _renderListPool[ id ]; + + if ( item === undefined ) { + + item = { + type: type, + data: data, + material: material + }; + + _renderListPool[ id ] = item; + + return item; + + } + + item.type = type; + item.data = data; + item.material = material; + + return item; } @@ -73941,9 +76111,9 @@ async function importThreeJs(original) { if (!isNodeJs() || (THREE.REVISION <= 162)) return THREE; - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(h1 => { + return import('three').then(h1 => { Object.assign(THREE, h1); - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }); + return import('three/addons'); }).then(h2 => { Object.assign(THREE, h2); return THREE; @@ -74431,12 +76601,12 @@ async function createRender3D(width, height, render3d, args) { promise = Promise.resolve(r); } else if (isNodeJs()) { // try to use WebGL inside node.js - need to create headless context - promise = Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(node_canvas => { + promise = import('canvas').then(node_canvas => { args.canvas = node_canvas.default.createCanvas(width, height); args.canvas.addEventListener = () => {}; // dummy args.canvas.removeEventListener = () => {}; // dummy args.canvas.style = {}; - return internals._node_gl || Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }); + return internals._node_gl || import('gl'); }).then(node_gl => { internals._node_gl = node_gl; const gl = node_gl?.default(width, height, { preserveDrawingBuffer: true }); @@ -75483,7 +77653,7 @@ class PointsCreator { let promise; if (isNodeJs()) { - promise = Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(handle => handle.default.loadImage(dataUrl).then(img => { + promise = import('canvas').then(handle => handle.default.loadImage(dataUrl).then(img => { const canvas = handle.default.createCanvas(64, 64), ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, 64, 64); @@ -75831,7 +78001,6 @@ createLatexGeometry: createLatexGeometry */ /* eslint-disable curly */ -/* eslint-disable no-loss-of-precision */ /* eslint-disable no-useless-assignment */ /* eslint-disable no-use-before-define */ /* eslint-disable no-else-return */ @@ -78629,7 +80798,7 @@ async function saveFile(filename, content) { if (isFunc(_saveFileFunc)) return _saveFileFunc(filename, getBinFileContent(content)); if (isNodeJs()) { - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(fs => { + return import('fs').then(fs => { fs.writeFileSync(filename, getBinFileContent(content)); return true; }); @@ -79020,6 +81189,20 @@ class JSRootMenu { this.endsub(); } + /** @summary Add log scale selection for pad + * @protected */ + addPadLogMenu(kind, value, func) { + this.sub('SetLog ' + kind, + () => this.input('Enter log kind: 0 - off, 1 - log10, 2 - log2, 3 - ln, ...', value, 'int', 0, 10000).then(func)); + this.addchk(value === 0, 'linear', () => func(0)); + this.addchk(value === 1, 'log10', () => func(1)); + this.addchk(value === 2, 'log2', () => func(2)); + this.addchk(value === 3, 'ln', () => func(3)); + this.addchk(value === 4, 'log4', () => func(4)); + this.addchk(value === 8, 'log8', () => func(8)); + this.endsub(); + } + /** @summary Add palette menu entries * @protected */ addPaletteMenu(curr, set_func) { @@ -79461,42 +81644,48 @@ class JSRootMenu { addTAxisMenu(EAxisBits, painter, faxis, kind, axis_painter, frame_painter) { const is_gaxis = faxis._typename === clTGaxis; - this.add('Divisions', () => this.input('Set Ndivisions', faxis.fNdivisions, 'int', 0).then(val => { - faxis.fNdivisions = val; painter.interactiveRedraw('pad', `exec:SetNdivisions(${val})`, kind); + this.add('Divisions', () => this.input('Set Ndivisions', is_gaxis ? faxis.fNdiv : faxis.fNdivisions, 'int').then(val => { + if (is_gaxis) + faxis.fNdiv = val; + else + faxis.fNdivisions = val; + painter.interactiveRedraw('pad', `exec:SetNdivisions(${val})`, kind); })); - this.sub('Labels'); - this.addchk(faxis.TestBit(EAxisBits.kCenterLabels), 'Center', - arg => { faxis.SetBit(EAxisBits.kCenterLabels, arg); painter.interactiveRedraw('pad', `exec:CenterLabels(${arg})`, kind); }); - this.addchk(faxis.TestBit(EAxisBits.kLabelsVert), 'Rotate', - arg => { faxis.SetBit(EAxisBits.kLabelsVert, arg); painter.interactiveRedraw('pad', `exec:SetBit(TAxis::kLabelsVert,${arg})`, kind); }); - this.addColorMenu('Color', faxis.fLabelColor, - arg => { faxis.fLabelColor = arg; painter.interactiveRedraw('pad', getColorExec(arg, 'SetLabelColor'), kind); }); - this.addSizeMenu('Offset', -0.02, 0.1, 0.01, faxis.fLabelOffset, - arg => { faxis.fLabelOffset = arg; painter.interactiveRedraw('pad', `exec:SetLabelOffset(${arg})`, kind); }); - let a = faxis.fLabelSize >= 1; - this.addSizeMenu('Size', a ? 2 : 0.02, a ? 30 : 0.11, a ? 2 : 0.01, faxis.fLabelSize, - arg => { faxis.fLabelSize = arg; painter.interactiveRedraw('pad', `exec:SetLabelSize(${arg})`, kind); }); - - if (frame_painter && (axis_painter?.kind === kAxisLabels) && (faxis.fNbins > 20)) { - this.add('Find label', () => this.input('Label id').then(id => { - if (!id) - return; - for (let bin = 0; bin < faxis.fNbins; ++bin) { - const lbl = axis_painter.formatLabels(bin); - if (lbl === id) - return frame_painter.zoomSingle(kind, Math.max(0, bin - 4), Math.min(faxis.fNbins, bin + 5)); - } - }), 'Zoom into region around specific label'); - } - if (frame_painter && faxis.fLabels) { - const ignore = `${kind}_ignore_labels`; - this.addchk(!frame_painter[ignore], 'Custom', flag => { - frame_painter[ignore] = !flag; - painter.interactiveRedraw('pad'); - }, `Use of custom labels in axis ${kind}`); + if (kind !== 'v') { + this.sub('Labels'); + this.addchk(faxis.TestBit(EAxisBits.kCenterLabels), 'Center', + arg => { faxis.SetBit(EAxisBits.kCenterLabels, arg); painter.interactiveRedraw('pad', `exec:CenterLabels(${arg})`, kind); }); + this.addchk(faxis.TestBit(EAxisBits.kLabelsVert), 'Rotate', + arg => { faxis.SetBit(EAxisBits.kLabelsVert, arg); painter.interactiveRedraw('pad', `exec:SetBit(TAxis::kLabelsVert,${arg})`, kind); }); + this.addColorMenu('Color', faxis.fLabelColor, + arg => { faxis.fLabelColor = arg; painter.interactiveRedraw('pad', getColorExec(arg, 'SetLabelColor'), kind); }); + this.addSizeMenu('Offset', -0.02, 0.1, 0.01, faxis.fLabelOffset, + arg => { faxis.fLabelOffset = arg; painter.interactiveRedraw('pad', `exec:SetLabelOffset(${arg})`, kind); }); + const a = faxis.fLabelSize >= 1; + this.addSizeMenu('Size', a ? 2 : 0.02, a ? 30 : 0.11, a ? 2 : 0.01, faxis.fLabelSize, + arg => { faxis.fLabelSize = arg; painter.interactiveRedraw('pad', `exec:SetLabelSize(${arg})`, kind); }); + + if (frame_painter && (axis_painter?.kind === kAxisLabels) && (faxis.fNbins > 20)) { + this.add('Find label', () => this.input('Label id').then(id => { + if (!id) + return; + for (let bin = 0; bin < faxis.fNbins; ++bin) { + const lbl = axis_painter.formatLabels(bin); + if (lbl === id) + return frame_painter.zoomSingle(kind, Math.max(0, bin - 4), Math.min(faxis.fNbins, bin + 5)); + } + }), 'Zoom into region around specific label'); + } + if (frame_painter && faxis.fLabels) { + const ignore = `${kind}_ignore_labels`; + this.addchk(!frame_painter[ignore], 'Custom', flag => { + frame_painter[ignore] = !flag; + painter.interactiveRedraw('pad'); + }, `Use of custom labels in axis ${kind}`); + } + this.endsub(); } - this.endsub(); this.sub('Title'); this.add('SetTitle', () => { @@ -79523,8 +81712,8 @@ class JSRootMenu { }); this.addSizeMenu('Offset', 0, 3, 0.2, faxis.fTitleOffset, arg => { faxis.fTitleOffset = arg; painter.interactiveRedraw('pad', `exec:SetTitleOffset(${arg})`, kind); }); - a = faxis.fTitleSize >= 1; - this.addSizeMenu('Size', a ? 2 : 0.02, a ? 30 : 0.11, a ? 2 : 0.01, faxis.fTitleSize, + const p = faxis.fTitleSize >= 1; + this.addSizeMenu('Size', p ? 2 : 0.02, p ? 30 : 0.11, p ? 2 : 0.01, faxis.fTitleSize, arg => { faxis.fTitleSize = arg; painter.interactiveRedraw('pad', `exec:SetTitleSize(${arg})`, kind); }); this.endsub(); @@ -79626,6 +81815,9 @@ class JSRootMenu { this.addchk(settings.StripAxisLabels, 'Strip labels', flag => { settings.StripAxisLabels = flag; }, 'Provide shorter labels like 10^0 -> 1'); this.addchk(settings.CutAxisLabels, 'Cut labels', flag => { settings.CutAxisLabels = flag; }, 'Remove labels which may exceed graphical range'); this.add(`Tilt angle ${settings.AxisTiltAngle}`, () => this.input('Axis tilt angle', settings.AxisTiltAngle, 'int', 0, 180).then(val => { settings.AxisTiltAngle = val; })); + this.add(`X format ${settings.XValuesFormat ?? gStyle.fStatFormat}`, () => this.input('X axis format', settings.XValuesFormat).then(val => { settings.XValuesFormat = val; })); + this.add(`Y format ${settings.YValuesFormat ?? gStyle.fStatFormat}`, () => this.input('Y axis format', settings.YValuesFormat).then(val => { settings.YValuesFormat = val; })); + this.add(`Z format ${settings.ZValuesFormat ?? gStyle.fStatFormat}`, () => this.input('Z axis format', settings.ZValuesFormat).then(val => { settings.ZValuesFormat = val; })); this.endsub(); this.addSelectMenu('Latex', ['Off', 'Symbols', 'Normal', 'MathJax', 'Force MathJax'], settings.Latex, value => { settings.Latex = value; }); this.addSelectMenu('3D rendering', ['Default', 'WebGL', 'Image'], settings.Render3D, value => { settings.Render3D = value; }); @@ -79824,9 +82016,14 @@ class JSRootMenu { * @param {string} [kind] - use 'text' (default), 'number', 'float' or 'int' * @protected */ async input(title, value, kind, min, max) { + let onchange = null; + if (isFunc(kind)) { + onchange = kind; + kind = ''; + } if (!kind) kind = 'text'; - const inp_type = (kind === 'int') ? 'number' : 'text'; + const inp_type = (kind === 'int') ? 'number' : 'text', value0 = value; let ranges = ''; if ((value === undefined) || (value === null)) value = ''; @@ -79839,24 +82036,33 @@ class JSRootMenu { const main_content = '
' + - `` + - '
'; + `` + + '', oninit = !onchange ? null : elem => { + const inp = elem.querySelector('.jsroot_dlginp'); + if (inp) + inp.oninput = () => onchange(inp.value); + }; return new Promise(resolveFunc => { - this.runModal(title, main_content, { btns: true, height: 150, width: 400 }).then(element => { - if (!element) + this.runModal(title, main_content, { btns: true, height: 150, width: 400, oninit }).then(element => { + if (!element) { + if (onchange) + onchange(value0); return; - let val = element.querySelector('.jsroot_dlginp').value; + } + let val = element.querySelector('.jsroot_dlginp').value, isok = true; if (kind === 'float') { val = Number.parseFloat(val); - if (Number.isFinite(val)) - resolveFunc(val); + isok = Number.isFinite(val); } else if (kind === 'int') { val = parseInt(val); - if (Number.isInteger(val)) - resolveFunc(val); - } else + isok = Number.isInteger(val); + } + if (isok) { + if (onchange) + onchange(val); resolveFunc(val); + } }); }); } @@ -80315,25 +82521,25 @@ class StandaloneMenu extends JSRootMenu { select(`#${dlg_id}`).remove(); select(`#${dlg_id}_block`).remove(); - const w = Math.min(args.width || 450, Math.round(0.9 * browser.screenWidth)); - modal.block = select('body').append('div') - .attr('id', `${dlg_id}_block`) - .attr('class', 'jsroot_dialog_block') - .attr('style', 'z-index: 100000; position: absolute; left: 0px; top: 0px; bottom: 0px; right: 0px; opacity: 0.2; background-color: white'); - modal.element = select('body') - .append('div') - .attr('id', dlg_id) - .attr('class', 'jsroot_dialog') - .style('position', 'absolute') - .style('width', `${w}px`) - .style('left', '50%') - .style('top', '50%') - .style('z-index', 100001) - .attr('tabindex', '0'); + const w = Math.min(args.width || 450, Math.round(0.9 * browser.screenWidth)), + b = select('body'); + modal.block = b.append('div') + .attr('id', `${dlg_id}_block`) + .attr('class', 'jsroot_dialog_block') + .attr('style', 'z-index: 100000; position: absolute; left: 0px; top: 0px; bottom: 0px; right: 0px; opacity: 0.2; background-color: white'); + modal.element = b.append('div') + .attr('id', dlg_id) + .attr('class', 'jsroot_dialog') + .style('position', 'absolute') + .style('width', `${w}px`) + .style('left', '50%') + .style('top', '50%') + .style('z-index', 100001) + .attr('tabindex', '0'); modal.element.html( '
' + - `
${title}
` + + `
${title}
` + `
${main_content}
` + '
' + `` + @@ -80341,6 +82547,16 @@ class StandaloneMenu extends JSRootMenu { '
' ); + const drag_move = drag().on('start', () => { modal.y0 = 0; }).on('drag', evnt => { + if (!modal.y0) + modal.y0 = pointer(evnt, modal.element.node())[1]; + let p0 = Math.max(0, pointer(evnt, b.node())[1] - modal.y0); + if (b.node().clientHeight) + p0 = Math.min(p0, 0.8 * b.node().clientHeight); + modal.element.style('top', `${p0}px`); + }); + modal.element.select('.jsroot_dialog_title').call(drag_move); + modal.done = function(res) { if (this._done) return; @@ -80383,6 +82599,8 @@ class StandaloneMenu extends JSRootMenu { f = modal.element.select('.jsroot_dialog_footer').select('button'); if (!f.empty()) f.node().focus(); + if (isFunc(args.oninit)) + args.oninit(modal.element.node()); return modal; } @@ -80776,7 +82994,7 @@ const AxisPainterMethods = { /** @summary Produce axis ticks */ produceTicks(ndiv, ndiv2) { - if (!this.noticksopt) { + if (!this.noticksopt && !this.exact_ticks) { const total = ndiv * (ndiv2 || 1); if (this.log) @@ -81021,7 +83239,7 @@ class TAxisPainter extends ObjectPainter { if (this.kind === kAxisFunc) this.func = this.createFuncHandle(opts.axis_func, this.logbase, smin, smax); else - this.func = log().base(this.logbase).domain([smin, smax]); + this.func = log$1().base(this.logbase).domain([smin, smax]); } else if (this.symlog) { let v = Math.max(Math.abs(smin), Math.abs(smax)); if (Number.isInteger(this.symlog) && (this.symlog > 0)) @@ -81049,14 +83267,18 @@ class TAxisPainter extends ObjectPainter { else this.gr = this.func; - delete this.format;// remove formatting func + delete this.format; // remove formatting func let ndiv = 508; if (this.is_gaxis) ndiv = axis.fNdiv; else if (axis) - ndiv = axis.fNdivisions ? Math.max(axis.fNdivisions, 4) : 0; + ndiv = axis.fNdivisions; + this.exact_ticks = ndiv < 0; + if (this.exact_ticks) + ndiv = Math.abs(ndiv); + ndiv = Math.max(ndiv, 4); this.nticks = ndiv % 100; this.nticks2 = (ndiv % 10000 - this.nticks) / 100; this.nticks3 = Math.floor(ndiv / 10000); @@ -81526,7 +83748,7 @@ class TAxisPainter extends ObjectPainter { if (handle.kind === 1) { // if not showing labels, not show large tick - // FIXME: for labels last tick is smaller, + // FIXME: for labels last tick is smaller if (!this.isExtraLogTick(handle.tick) && (this.format(handle.tick, true) !== null)) h1 = tickSize; this.ticks.push(handle.grpos); // keep graphical positions of major ticks @@ -84867,21 +87089,9 @@ class TFramePainter extends FrameInteractive { } menu.endsub(); - if (pad) { - const member = 'fLog' + kind[0]; - menu.sub('SetLog ' + kind[0], () => { - menu.input('Enter log kind: 0 - off, 1 - log10, 2 - log2, 3 - ln, ...', pad[member], 'int', 0, 10000).then(v => { - this.changeAxisLog(kind[0], v); - }); - }); - menu.addchk(pad[member] === 0, 'linear', () => this.changeAxisLog(kind[0], 0)); - menu.addchk(pad[member] === 1, 'log10', () => this.changeAxisLog(kind[0], 1)); - menu.addchk(pad[member] === 2, 'log2', () => this.changeAxisLog(kind[0], 2)); - menu.addchk(pad[member] === 3, 'ln', () => this.changeAxisLog(kind[0], 3)); - menu.addchk(pad[member] === 4, 'log4', () => this.changeAxisLog(kind[0], 4)); - menu.addchk(pad[member] === 8, 'log8', () => this.changeAxisLog(kind[0], 8)); - menu.endsub(); - } + if (pad) + menu.addPadLogMenu(kind[0], pad[`fLog${kind[0]}`], v => this.changeAxisLog(kind[0], v)); + menu.addchk(faxis.TestBit(EAxisBits.kMoreLogLabels), 'More log', flag => { faxis.SetBit(EAxisBits.kMoreLogLabels, flag); if (hist_painter?.getSnapId() && (kind.length === 1)) @@ -86647,7 +88857,7 @@ class BatchDisplay extends MDIDisplay { if (!mainsvg.attr('width') && !mainsvg.attr('height')) mainsvg.attr('width', this.width).attr('height', this.height); - if (style_filter) + if (style_filter && (style_filter !== 'none')) mainsvg.style('filter', style_filter); function clear_element() { @@ -90363,7 +92573,7 @@ class TCanvasPainter extends TPadPainter { /** @summary Function called when canvas menu item Save is called */ saveCanvasAsFile(fname) { - const pnt = fname.indexOf('.'); + const pnt = fname.lastIndexOf('.'); this.createImage(fname.slice(pnt + 1)) .then(res => this.sendWebsocket(`SAVE:${fname}:${res}`)); } @@ -91032,6 +93242,20 @@ class TCanvasPainter extends TPadPainter { this.getWebsocket()?.resizeWindow(fullW, fullH); } + /** @summary create three.js object for TCanvas */ + static async build3d(can, opt, get_painter) { + const painter = new TCanvasPainter(null, can, opt, true); + painter.checkSpecialsInPrimitives(can, true); + + const fp = new TFramePainter(null, null); + // return dummy frame painter as result + painter.getFramePainter = () => fp; + + return painter.drawPrimitives().then(() => { + return get_painter ? painter : fp.create3DScene(-1, true); + }); + } + /** @summary draw TCanvas */ static async draw(dom, can, opt) { const nocanvas = !can; @@ -91202,18 +93426,26 @@ class TPavePainter extends ObjectPainter { tm = pad?.fTopMargin ?? gStyle.fPadTopMargin, bm = pad?.fBottomMargin ?? gStyle.fPadBottomMargin; - return svgToImage(svg_code).then(canvas => { - if (!canvas) + return svgToImage(svg_code, 'rgba').then(image => { + if (!image) + return false; + + let arr = image.data; + const width = image.width, height = image.height; + + if (!arr && isFunc(image.getContext) && image.getContext('2d')) + arr = image.getContext('2d').getImageData(0, 0, width, height).data; + + if (!arr) return false; let nX = 100, nY = 100; - const context = canvas.getContext('2d'), - arr = context.getImageData(0, 0, canvas.width, canvas.height).data, - boxW = Math.floor(canvas.width / nX), boxH = Math.floor(canvas.height / nY), + const boxW = Math.floor(width / nX), + boxH = Math.floor(height / nY), raster = new Array(nX * nY); - if (arr.length !== canvas.width * canvas.height * 4) { - console.log(`Image size missmatch in TLegend autoplace ${arr.length} expected ${canvas.width * canvas.height * 4}`); + if (arr.length !== width * height * 4) { + console.log(`Image size missmatch in TLegend autoplace ${arr.length} expected ${width * height * 4}`); nX = nY = 0; } @@ -91225,7 +93457,7 @@ class TPavePainter extends ObjectPainter { for (let x = px1; (x < px2) && !filled; ++x) { for (let y = py1; y < py2; ++y) { - const indx = (y * canvas.width + x) * 4; + const indx = (y * width + x) * 4; if (arr[indx] || arr[indx + 1] || arr[indx + 2] || arr[indx + 3]) { filled = 1; break; @@ -91303,6 +93535,11 @@ class TPavePainter extends ObjectPainter { opt = this.getPaveDrawOption().toUpperCase(), fp = this.getFramePainter(), pp = this.getPadPainter(), pad = pp.getRootPad(true); + + // special handling of dummy frame painter + if (fp?.getDrawDom() === null) + return this; + let interactive_element, width, height; if (pt.fInit === 0) { @@ -91909,7 +94146,7 @@ class TPavePainter extends ObjectPainter { nlines = legend.fPrimitives.arr.length, ncols = Math.max(1, legend.fNColumns); let nrows = Math.round(nlines / ncols), - any_text = false, + any_text = false, has_header = false, custom_textg = false; // each text entry has own attributes if (nrows * ncols < nlines) @@ -91919,6 +94156,8 @@ class TPavePainter extends ObjectPainter { for (let ii = 0; ii < nlines; ++ii) { const entry = legend.fPrimitives.arr[ii]; + if ((ii === 0) && (entry.fOption === 'h')) + has_header = true; if (isEmpty(entry)) { if (ncols === 1) nrows--; @@ -91930,6 +94169,9 @@ class TPavePainter extends ObjectPainter { } } + if (has_header && (ncols > 1) && ((nrows - 1) * ncols < nlines - 1)) + nrows++; + if (nrows < 1) nrows = 1; @@ -91992,8 +94234,10 @@ class TPavePainter extends ObjectPainter { if (ncols === 1) ++i; - else + else if (!has_header || ii === 0) i = ii; + else + i = ii - 1 + ncols; const lopt = entry.fOption.toLowerCase(), icol = i % ncols, irow = (i - icol) / ncols, @@ -92098,17 +94342,19 @@ class TPavePainter extends ObjectPainter { .call(painter.lineatt.func); } - let pos_x = tpos_x; + let pos_x = tpos_x, arg_width = Math.round(column_pos[icol + 1] - pos_x); if (isStr(lopt) && (lopt.toLowerCase() !== 'h')) any_opt = true; - else if (!any_opt) - pos_x = x0; + else if (!any_opt) { + pos_x = padding_x; + arg_width = w - 2 * padding_x; + } if (entry.fLabel) { const textatt = this.createAttText({ attr: entry, std: false, attr_alt: legend }), arg = { draw_g: this.getG(), align: textatt.align, - x: pos_x, width: Math.round(column_pos[icol + 1] - pos_x), + x: pos_x, width: arg_width, y: y0, height: Math.round(row_height), scale: (custom_textg && !entry.fTextSize) || !legend.fTextSize, text: entry.fLabel, color: textatt.color @@ -92148,10 +94394,10 @@ class TPavePainter extends ObjectPainter { height = pp.getPadHeight(), pad = pp.getRootPad(true), main = palette.$main_painter || this.getMainPainter(), + is_th3 = isFunc(main.getDimension) && (main.getDimension() === 3), fp = this.getFramePainter(), - contour = main.getContour(false), + contour = main.getContour(is_th3), levels = contour?.getLevels(), - is_th3 = isFunc(main.getDimension) && (main.getDimension() === 3), is_scatter = isFunc(main.getZaxis), log = pad?.fLogv ?? (is_th3 ? false : pad?.fLogz), draw_palette = main.getHistPalette(), @@ -92161,6 +94407,7 @@ class TPavePainter extends ObjectPainter { let zmin = 0, zmax = 100, gzmin, gzmax, axis_transform, axis_second = 0; this.#palette_vertical = (palette.fX2NDC - palette.fX1NDC) < (palette.fY2NDC - palette.fY1NDC); + this.is_th3 = is_th3; axis.fTickSize = 0.03; // adjust axis ticks size @@ -92197,12 +94444,16 @@ class TPavePainter extends ObjectPainter { } } else if ((main.gmaxbin !== undefined) && (main.gminbin !== undefined)) { // this is case of TH2 (needs only for size adjustment) - zmin = main.gminbin; - zmax = main.gmaxbin; + gzmin = zmin = main.gminbin; + gzmax = zmax = main.gmaxbin; + if (contour?.colzmin !== undefined && contour?.colzmax !== undefined) { + zmin = contour.colzmin; + zmax = contour.colzmax; + } } else if ((main.hmin !== undefined) && (main.hmax !== undefined)) { // this is case of TH1 - zmin = main.hmin; - zmax = main.hmax; + gzmin = zmin = main.hmin; + gzmax = zmax = main.hmax; } g.selectAll('rect').style('fill', 'white'); @@ -92374,6 +94625,17 @@ class TPavePainter extends ObjectPainter { zoom_rect.attr('x', Math.min(sel1, sel2)) .attr('width', Math.abs(sel2 - sel1)); } + }, zoomPalette = (z1, z2) => { + if (!this.is_th3) + return this.getFramePainter().zoomSingle('z', z1, z2, true); + const maino = this.getMainPainter().options; + if (z1 === z2) + maino.minimum = maino.maximum = kNoZoom; + else { + maino.minimum = z1; + maino.maximum = z2; + } + this.interactiveRedraw('pad'); }, endRectSel = evnt => { if (!doing_zoom) return; @@ -92385,10 +94647,13 @@ class TPavePainter extends ObjectPainter { zoom_rect = null; doing_zoom = false; + if (sel1 === sel2) + return; + const z1 = this.z_handle.revertPoint(sel1), z2 = this.z_handle.revertPoint(sel2); - this.getFramePainter().zoomSingle('z', Math.min(z1, z2), Math.max(z1, z2), true); + zoomPalette(Math.min(z1, z2), Math.max(z1, z2)); }, startRectSel = evnt => { // ignore when touch selection is activated if (doing_zoom) @@ -92423,7 +94688,7 @@ class TPavePainter extends ObjectPainter { if (settings.Zooming) { this.getG().selectAll('.axis_zoom') .on('mousedown', startRectSel) - .on('dblclick', () => this.getFramePainter().zoomSingle('z', 0, 0, true)); + .on('dblclick', () => zoomPalette(0, 0)); } if (settings.ZoomWheel) { @@ -92432,7 +94697,7 @@ class TPavePainter extends ObjectPainter { coord = this.#palette_vertical ? (1 - pos[1] / s_height) : pos[0] / s_width, item = this.z_handle.analyzeWheelEvent(evnt, coord); if (item?.changed) - this.getFramePainter().zoomSingle('z', item.min, item.max, true); + zoomPalette(item.min, item.max); }); } } @@ -92545,9 +94810,9 @@ class TPavePainter extends ObjectPainter { }); const addStatOpt = (pos, name) => { let sopt = (pos < 10) ? pave.fOptStat : pave.fOptFit; - sopt = parseInt(parseInt(sopt) / parseInt(Math.pow(10, pos % 10))) % 10; + sopt = Math.floor(parseInt(sopt) / parseInt(Math.pow(10, pos % 10))) % 10; menu.addchk(sopt, name, sopt * 100 + pos, arg => { - const oldopt = parseInt(arg / 100); + const oldopt = Math.floor(arg / 100); let newopt = (arg % 100 < 10) ? pave.fOptStat : pave.fOptFit; newopt -= (oldopt > 0 ? oldopt : -1) * parseInt(Math.pow(10, arg % 10)); if (arg % 100 < 10) { @@ -92637,12 +94902,51 @@ class TPavePainter extends ObjectPainter { /** @summary Show pave context menu */ paveContextMenu(evnt) { - if (this.z_handle) { + if (!this.z_handle) + return showPainterMenu(evnt, this); + if (!this.is_th3) { const fp = this.getFramePainter(); if (isFunc(fp?.showContextMenu)) fp.showContextMenu('pal', evnt); - } else - showPainterMenu(evnt, this); + return; + } + + const pp = this.getPadPainter(), + pad = pp?.getRootPad(true), + faxis = this.z_handle.getObject(), + hist_painter = this.z_handle.hist_painter || this.getMainPainter(true); + + if (!pad || !hist_painter) + return; + + if (isFunc(evnt?.stopPropagation)) { + evnt.preventDefault(); + evnt.stopPropagation(); // disable main context menu + } + + createMenu(evnt, this).then(menu => { + menu.header('V axis', `${urlClassPrefix}${clTAxis}.html`); + + menu.addPadLogMenu('v', pad.fLogv || 0, v => { + pad.fLogv = v; + this.interactiveRedraw('pad', 'log'); + }); + + menu.addchk(faxis.TestBit(EAxisBits.kMoreLogLabels), 'More log', flag => { + faxis.SetBit(EAxisBits.kMoreLogLabels, flag); + this.interactiveRedraw('pad'); + }); + menu.addchk(faxis.TestBit(EAxisBits.kNoExponent), 'No exponent', flag => { + faxis.SetBit(EAxisBits.kNoExponent, flag); + this.interactiveRedraw('pad'); + }); + + hist_painter.fillPaletteMenu(menu, false); + + menu.addTAxisMenu(EAxisBits, hist_painter || this, faxis, 'v', this.z_handle, null); + + menu.show(); + }); } /** @summary Returns true when stat box is drawn */ @@ -93014,6 +95318,7 @@ kPosTitle: kPosTitle const kCARTESIAN = 1, kPOLAR = 2, kCYLINDRICAL = 3, kSPHERICAL = 4, kRAPIDITY = 5, kNormal$1 = 0, kPoisson = 1, kPoisson2 = 2, kOnlyCheck = 'only-check'; + /** * @summary Class to decode histograms draw options * @desc All options started from capital letter are major drawing options @@ -94010,7 +96315,7 @@ class FunctionsHandler { #painter; // object painter to which functions belongs #pad_painter; // pad painter - constructor(painter, pp, funcs, statpainter) { + constructor(painter, pp, funcs, statpainter, update_statpainter) { this.#painter = painter; this.#pad_painter = pp; @@ -94069,6 +96374,8 @@ class FunctionsHandler { const indx = painters.indexOf(statpainter); if (indx >= 0) painters.splice(indx, 1); + if (update_statpainter && (update_painters.indexOf(statpainter) < 0)) + update_painters.push(statpainter); } // remove all function which are not found in new list of functions @@ -94139,6 +96446,7 @@ class THistPainter extends ObjectPainter { #auto_exec; // can be reused when sending option back to server #funcs_handler; // special instance for functions drawing #contour; // histogram colors contour + #create_stats; // if stats was created by painter /** @summary Constructor * @param {object|string} dom - DOM element for drawing or element id @@ -94442,7 +96750,7 @@ class THistPainter extends ObjectPainter { histo.fBins = obj.fBins; // remove old functions, update existing, prepare to draw new one - this.#funcs_handler = new FunctionsHandler(this, pp, obj.fFunctions, statpainter); + this.#funcs_handler = new FunctionsHandler(this, pp, obj.fFunctions, statpainter, this.#create_stats); const changed_opt = (histo.fOption !== obj.fOption); histo.fOption = obj.fOption; @@ -94767,7 +97075,7 @@ class THistPainter extends ObjectPainter { /** @summary Returns true if stats box fill can be ignored */ isIgnoreStatsFill() { - return !this.getObject() || (!this.draw_content && !this.create_stats && !this.hasSnapId()); + return !this.getObject() || (!this.draw_content && !this.#create_stats && !this.hasSnapId()); } /** @summary Create stat box for histogram if required */ @@ -94806,7 +97114,7 @@ class THistPainter extends ObjectPainter { if (!stats && !optstat && !optfit) return null; - this.create_stats = true; + this.#create_stats = true; if (stats) return stats; @@ -95281,6 +97589,12 @@ class THistPainter extends ObjectPainter { return cntr; } + /** @summary Reset contour object + * @private */ + resetContour() { + this.#contour = undefined; + } + /** @summary Return Z-scale ranges to create contour */ #getContourRanges(main, fp) { const o = this.getOptions(), @@ -95861,7 +98175,7 @@ class THistPainter extends ObjectPainter { this.maxbin = this.minbin = 0; // force recalculation of z levels - this.#contour = undefined; + this.resetContour(); if (args.zrange) Object.assign(res, this.#getContourRanges(this.getMainPainter(), this.getFramePainter())); @@ -99175,11 +101489,11 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { this.assignChordCircInteractive(midx, midy); - const chord$1 = chord() + const chord = chord_default() .padAngle(10 / innerRadius) .sortSubgroups(d3_descending) .sortChords(d3_descending), - chords = chord$1(data), + chords = chord(data), group = g.append('g') .attr('font-size', 10) .attr('font-family', 'sans-serif') @@ -99187,7 +101501,7 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { .data(chords.groups) .join('g'), arc$1 = arc().innerRadius(innerRadius).outerRadius(outerRadius), - ribbon = ribbon$1().radius(innerRadius - 1).padAngle(1 / innerRadius); + ribbon = ribbon_default().radius(innerRadius - 1).padAngle(1 / innerRadius); function ticks({ startAngle, endAngle, value }) { const k = (endAngle - startAngle) / value, @@ -104524,6 +106838,9 @@ class TH3Painter extends THistPainter { const histo = this.getHisto(), fp = this.getFramePainter(); + // ensure proper colors + this.resetContour(); + let use_lambert = false, use_helper = false, use_colors = false, use_opacity = 1, exclude_content = -1, logv = this.getPadPainter()?.getRootPad()?.fLogv, @@ -104597,19 +106914,6 @@ class TH3Painter extends THistPainter { } else if (use_scale) use_scale = (this.gminbin || this.gmaxbin) ? 1 / Math.max(Math.abs(this.gminbin), Math.abs(this.gmaxbin)) : 1; - const get_bin_weight = content => { - if ((exclude_content >= 0) && (content < exclude_content)) - return 0; - if (!use_scale) - return 1; - if (logv) { - if (content <= 0) - return 0; - content = Math.log(content) - scale_offset; - } - return Math.pow(Math.abs(content * use_scale), 0.3333); - }; - // eslint-disable-next-line one-var const i1 = this.getSelectIndex('x', 'left', 0.5), i2 = this.getSelectIndex('x', 'right', 0), j1 = this.getSelectIndex('y', 'left', 0.5), @@ -104623,7 +106927,19 @@ class TH3Painter extends THistPainter { const cntr = use_colors ? this.getContour() : null, palette = use_colors ? this.getHistPalette() : null, bins_matrixes = [], bins_colors = [], bins_ids = [], negative_matrixes = [], bin_opacities = [], - transfer = (this.transferFunc && proivdeEvalPar(this.transferFunc, true)) ? this.transferFunc : null; + transfer = (this.transferFunc && proivdeEvalPar(this.transferFunc, true)) ? this.transferFunc : null, + get_bin_weight = content => { + if ((exclude_content >= 0) && (content < exclude_content)) + return 0; + if (!use_scale) + return 1; + if (logv) { + if (content <= 0) + return 0; + content = Math.log(content) - scale_offset; + } + return Math.pow(Math.abs(content * use_scale), 0.3333); + }; for (let i = i1; i < i2; ++i) { const grx1 = fp.grx(histo.fXaxis.GetBinLowEdge(i + 1)), @@ -105029,11 +107345,14 @@ let TGraphPainter$1 = class TGraphPainter extends ObjectPainter { return true; let is_normal = false; - if (check_axis !== 'y') - is_normal ||= (histo.fXaxis.fXmin !== 0.0011) || (histo.fXaxis.fXmax !== 1.1); + if (check_axis !== 'y') { + is_normal ||= ((histo.fXaxis.fXmin !== 0.0011) && (histo.fXaxis.fXmin !== 0)) || + ((histo.fXaxis.fXmax !== 1.1) && (histo.fXaxis.fXmax !== 1)); + } if (check_axis !== 'x') { - is_normal ||= (histo.fYaxis.fXmin !== 0.0011) || (histo.fYaxis.fXmax !== 1.1) || + is_normal ||= ((histo.fYaxis.fXmin !== 0.0011) && (histo.fYaxis.fXmin !== 0)) || + ((histo.fYaxis.fXmax !== 1.1) && (histo.fYaxis.fXmax !== 1)) || (histo.fMinimum !== 0.0011) || (histo.fMaximum !== 1.1); } @@ -106464,7 +108783,7 @@ let TGraphPainter$1 = class TGraphPainter extends ObjectPainter { } /** @summary Complete moving */ - moveEnd(not_changed) { + moveEnd(not_changed, evnt) { const graph = this.getGraph(), last = graph?.fNpoints - 1; let exec = ''; @@ -106494,6 +108813,17 @@ let TGraphPainter$1 = class TGraphPainter extends ObjectPainter { else this.drawGraph(); } + } else if (not_changed) { + const fp = this.getFramePainter(), + m = pointer(evnt, fp.getFrameSvg().node()), + fw = fp.getFrameWidth(), fh = fp.getFrameHeight(), + valid_x = (m[0] >= 0) && (m[0] <= fw), + valid_y = (m[1] >= 0) && (m[1] <= fh); + if (valid_x && valid_y) { + evnt.preventDefault(); + evnt.stopPropagation(); + fp.processFrameClick({ x: m[0], y: m[1] }); + } } else { changeBin(this.#move_bin); this.#move_binindx = undefined; @@ -106693,8 +109023,6 @@ let TGraphPainter$1 = class TGraphPainter extends ObjectPainter { if (!st.fOptFit || this.getCanvPainter()?.getRootPad(true)?.fPrimitives?.arr.length) return null; - this.create_stats = true; - stats = create$1(clTPaveStats); Object.assign(stats, { fName: 'stats', fOptStat: 0, fOptFit: st.fOptFit, fBorderSize: 1, @@ -109829,7 +112157,6 @@ function createMatrix(matrix) { break; case 'TGeoGenTrans': scale = matrix.fScale; // no break, translation and rotation follows - // eslint-disable-next-line no-fallthrough case 'TGeoCombiTrans': translation = matrix.fTranslation; rotation = matrix.fRotation?.fRotationMatrix; @@ -110199,7 +112526,6 @@ createGeometry = function(shape, limit = 0) { case clTGeoHalfSpace: if (limit < 0) return 1; // half space if just plane used in composite - // eslint-disable-next-line no-fallthrough default: geoWarn(`unsupported shape type ${shape._typename}`); } @@ -110339,7 +112665,6 @@ function provideObjectInfo(obj) { break; case clTGeoTrd2: info.push(`Dy1=${conv(shape.fDy1)} Dy2=${conv(shape.fDy1)}`); // no break - // eslint-disable-next-line no-fallthrough case clTGeoTrd1: info.push(`Dx1=${conv(shape.fDx1)} Dx2=${conv(shape.fDx1)}`); break; @@ -110350,7 +112675,6 @@ function provideObjectInfo(obj) { break; case clTGeoConeSeg: info.push(`Phi1=${shape.fPhi1} Phi2=${shape.fPhi2}`); - // eslint-disable-next-line no-fallthrough case clTGeoCone: info.push(`Rmin1=${conv(shape.fRmin1)} Rmax1=${conv(shape.fRmax1)}`, `Rmin2=${conv(shape.fRmin2)} Rmax2=${conv(shape.fRmax2)}`); @@ -110358,7 +112682,6 @@ function provideObjectInfo(obj) { case clTGeoCtub: case clTGeoTubeSeg: info.push(`Phi1=${shape.fPhi1} Phi2=${shape.fPhi2}`); - // eslint-disable-next-line no-fallthrough case clTGeoEltu: case clTGeoTube: info.push(`Rmin=${conv(shape.fRmin)} Rmax=${conv(shape.fRmax)}`); @@ -110399,7 +112722,6 @@ function provideObjectInfo(obj) { break; case clTGeoGtra: info.push(`TwistAngle=${conv(shape.fTwistAngle)}`); - // eslint-disable-next-line no-fallthrough case clTGeoTrap: info.push(`Phi=${conv(shape.fPhi)} Theta=${conv(shape.fTheta)}`); break; @@ -117583,7 +119905,6 @@ class TGeoPainter extends ObjectPainter { break; case 'mix': this.#camera.add(new THREE.AmbientLight(0xefefef, p)); - // eslint-disable-next-line no-fallthrough default: // 6 point lights for (let n = 0; n < 6; ++n) { const l = new THREE.DirectionalLight(0xefefef, p); @@ -119327,7 +121648,7 @@ class TGeoPainter extends ObjectPainter { let pr; if (isNodeJs()) { - pr = Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(h => { + pr = import('node:worker_threads').then(h => { const wrk = new h.Worker(exports.source_dir.slice(7) + 'modules/geom/nodeworker.mjs', { type: 'module' }); wrk.on('message', msg => this.processWorkerReply(msg)); return wrk; @@ -121143,7 +123464,7 @@ const clTStreamerElement = 'TStreamerElement', clTStreamerObject = 'TStreamerObj clTQObject = 'TQObject', clTBasket = 'TBasket', clTDatime = 'TDatime', nameStreamerInfo = 'StreamerInfo', - kChar = 1, kShort = 2, kInt = 3, kLong = 4, kFloat = 5, kCounter = 6, + kChar$1 = 1, kShort = 2, kInt = 3, kLong = 4, kFloat = 5, kCounter = 6, kCharStar = 7, kDouble = 8, kDouble32 = 9, kLegacyChar = 10, kUChar = 11, kUShort = 12, kUInt = 13, kULong = 14, kBits = 15, kLong64 = 16, kULong64 = 17, kBool = 18, kFloat16 = 19, @@ -121179,7 +123500,13 @@ const clTStreamerElement = 'TStreamerElement', clTStreamerObject = 'TStreamerObj StlNames = ['', 'vector', 'list', 'deque', 'map', 'multimap', 'set', 'multiset', 'bitset'], // TObject bits - kIsReferenced = BIT(4), kHasUUID = BIT(5); + kIsReferenced = BIT(4), kHasUUID = BIT(5), + + // gap in http which can be merged into single http request + kMinimalHttpGap = 128, + + // temporary name assigned for file derived from binary buffer + kTmpFileName = 'localfile.root'; /** @summary Custom streamers for root classes @@ -121783,7 +124110,7 @@ function getTypeId(typname, norecursion) { case 'Bool_t': return kBool; case 'char': case 'signed char': - case 'Char_t': return kChar; + case 'Char_t': return kChar$1; case 'Color_t': case 'Style_t': case 'Width_t': @@ -121844,7 +124171,7 @@ function getArrayKind(type_name) { case 'D': return kDouble; case 'F': return kFloat; case 'S': return kShort; - case 'C': return kChar; + case 'C': return kChar$1; case 'L': return kLong; default: return -1; } @@ -122109,7 +124436,7 @@ function readMapElement(buf) { /** @summary create member entry for streamer element * @desc used for reading of data * @private */ -function createMemberStreamer(element, file) { +function createMemberStreamer(element, file, no_string) { const member = { name: element.fName, type: element.fType, fArrayLength: element.fArrayLength, @@ -122175,6 +124502,7 @@ function createMemberStreamer(element, file) { case kOffsetL + kInt: case kOffsetL + kCounter: case kOffsetL + kDouble: + case kOffsetL + kChar$1: case kOffsetL + kUChar: case kOffsetL + kShort: case kOffsetL + kUShort: @@ -122187,36 +124515,35 @@ function createMemberStreamer(element, file) { case kOffsetL + kFloat: if (element.fArrayDim < 2) { member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { - obj[this.name] = buf.readFastArray(this.arrlength, this.type - kOffsetL); - }; + if ((member.type !== kOffsetL + kChar$1) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = buf.readFastArray(this.arrlength, this.type - kOffsetL); + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = buf.readFastString(this.arrlength); + }; + } } else { - member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; member.minus1 = true; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => - buf2.readFastArray(handle.arrlength, handle.type - kOffsetL)); - }; - } - break; - case kOffsetL + kChar: - if (element.fArrayDim < 2) { - member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { - obj[this.name] = buf.readFastString(this.arrlength); - }; - } else { - member.minus1 = true; // one dimension used for char* member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => - buf2.readFastString(handle.arrlength)); - }; + if ((member.type !== kOffsetL + kChar$1) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => + buf2.readFastArray(handle.arrlength, handle.type - kOffsetL)); + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => + buf2.readFastString(handle.arrlength)); + }; + } } break; case kOffsetP + kBool: case kOffsetP + kInt: case kOffsetP + kDouble: + case kOffsetP + kChar$1: case kOffsetP + kUChar: case kOffsetP + kShort: case kOffsetP + kUShort: @@ -122228,21 +124555,20 @@ function createMemberStreamer(element, file) { case kOffsetP + kLong64: case kOffsetP + kFloat: member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? buf.readFastArray(obj[this.cntname], this.type - kOffsetP) : []; - }; - break; - case kOffsetP + kChar: - member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? buf.readFastString(obj[this.cntname]) : null; - }; + if ((member.type !== kOffsetP + kChar$1) || no_string) { + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? buf.readFastArray(obj[this.cntname], this.type - kOffsetP) : []; + }; + } else { + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? buf.readFastString(obj[this.cntname]) : null; + }; + } break; case kDouble32: case kOffsetL + kDouble32: case kOffsetP + kDouble32: member.double32 = true; - // eslint-disable-next-line no-fallthrough case kFloat16: case kOffsetL + kFloat16: case kOffsetP + kFloat16: @@ -122250,20 +124576,17 @@ function createMemberStreamer(element, file) { member.factor = 1 / element.fFactor; member.min = element.fXmin; member.read = function(buf) { return buf.ntou4() * this.factor + this.min; }; - } else - if ((element.fXmin === 0) && member.double32) - member.read = function(buf) { return buf.ntof(); }; - else { - member.nbits = Math.round(element.fXmin); - if (member.nbits === 0) - member.nbits = 12; - member.dv = new DataView(new ArrayBuffer(8), 0); // used to cast from uint32 to float32 - member.read = function(buf) { - const theExp = buf.ntou1(), theMan = buf.ntou2(); - this.dv.setUint32(0, (theExp << 23) | ((theMan & ((1 << (this.nbits + 1)) - 1)) << (23 - this.nbits))); - return ((1 << (this.nbits + 1) & theMan) ? -1 : 1) * this.dv.getFloat32(0); - }; - } + } else if ((element.fXmin === 0) && member.double32) + member.read = function(buf) { return buf.ntof(); }; + else { + member.nbits = Math.round(element.fXmin) || 12; + member.dv = new DataView(new ArrayBuffer(8), 0); // used to cast from uint32 to float32 + member.read = function(buf) { + const theExp = buf.ntou1(), theMan = buf.ntou2(); + this.dv.setUint32(0, (theExp << 23) | ((theMan & ((1 << (this.nbits + 1)) - 1)) << (23 - this.nbits))); + return ((1 << (this.nbits + 1) & theMan) ? -1 : 1) * this.dv.getFloat32(0); + }; + } member.readarr = function(buf, len) { const arr = this.double32 ? new Float64Array(len) : new Float32Array(len); @@ -122274,23 +124597,21 @@ function createMemberStreamer(element, file) { if (member.type < kOffsetL) member.func = function(buf, obj) { obj[this.name] = this.read(buf); }; - else - if (member.type > kOffsetP) { - member.cntname = element.fCountName; - member.func = function(buf, obj) { - obj[this.name] = (buf.ntou1() === 1) ? this.readarr(buf, obj[this.cntname]) : null; - }; - } else - if (element.fArrayDim < 2) { - member.arrlength = element.fArrayLength; - member.func = function(buf, obj) { obj[this.name] = this.readarr(buf, this.arrlength); }; - } else { - member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; - member.minus1 = true; - member.func = function(buf, obj) { - obj[this.name] = buf.readNdimArray(this, (buf2, handle) => handle.readarr(buf2, handle.arrlength)); - }; - } + else if (member.type > kOffsetP) { + member.cntname = element.fCountName; + member.func = function(buf, obj) { + obj[this.name] = (buf.ntou1() === 1) ? this.readarr(buf, obj[this.cntname]) : null; + }; + } else if (element.fArrayDim < 2) { + member.arrlength = element.fArrayLength; + member.func = function(buf, obj) { obj[this.name] = this.readarr(buf, this.arrlength); }; + } else { + member.arrlength = element.fMaxIndex[element.fArrayDim - 1]; + member.minus1 = true; + member.func = function(buf, obj) { + obj[this.name] = buf.readNdimArray(this, (buf2, handle) => handle.readarr(buf2, handle.arrlength)); + }; + } break; case kAnyP: @@ -122352,7 +124673,7 @@ function createMemberStreamer(element, file) { }; break; } - case kChar: + case kChar$1: member.func = function(buf, obj) { obj[this.name] = buf.ntoi1(); }; break; case kCharStar: @@ -123379,7 +125700,7 @@ async function R__unzip(arr, tgtsize, noalert, src_shift) { promise = new Promise(resolveFunc => { internals._ZstdInit.push(resolveFunc); }); else { internals._ZstdInit = []; - promise = (isNodeJs() ? Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }) : Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; })) + promise = (isNodeJs() ? import('@oneidentity/zstd-js') : import('./base/zstd.mjs')) .then(({ ZstdInit }) => ZstdInit()) .then(({ ZstdStream }) => { internals._ZstdStream = ZstdStream; @@ -123401,7 +125722,7 @@ async function R__unzip(arr, tgtsize, noalert, src_shift) { return nextPortion(); }); } else if (fmt === 'LZMA') { - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(lzma => { + return import('./base/lzma.mjs').then(lzma => { const expected_len = (getCode(curr + 6) & 0xff) | ((getCode(curr + 7) & 0xff) << 8) | ((getCode(curr + 8) & 0xff) << 16), reslen = lzma.decompress(uint8arr, tgt8arr, expected_len); fullres += reslen; @@ -123671,7 +125992,7 @@ class TBuffer { for (; i < n; ++i, o += 2) array[i] = view.getUint16(o); break; - case kChar: + case kChar$1: array = new Int8Array(n); for (; i < n; ++i) array[i] = view.getInt8(o++); @@ -124132,8 +126453,14 @@ class TFile { this.fAcceptRanges = false; } - const pos = Math.max(this.fURL.lastIndexOf('/'), this.fURL.lastIndexOf('\\')); - this.fFileName = pos >= 0 ? this.fURL.slice(pos + 1) : this.fURL; + this.assignFileName(this.fURL); + } + + assignFileName(url) { + if (isStr(url)) { + const pos = Math.max(url.lastIndexOf('/'), url.lastIndexOf('\\')); + this.fFileName = (pos >= 0) && (pos < url.length - 2) ? url.slice(pos + 1) : url; + } } /** @summary Set timeout for File instance @@ -124172,6 +126499,63 @@ class TFile { * @private */ async _open() { return this.readKeys(); } + /** @summary check if requested segments can be reordered or merged + * @private */ + #checkNeedReorder(place) { + let res = false, resort = false; + for (let n = 0; n < place.length - 2; n += 2) { + if (place[n] > place[n + 2]) + res = resort = true; + if (place[n] + place[n + 1] > place[n + 2] - kMinimalHttpGap) + res = true; + } + if (!res) { + return { + place, + blobs: [], + expectedSize(indx) { return this.place[indx + 1]; }, + addBuffer(indx, buf, o) { + this.blobs[indx / 2] = new DataView(buf, o, this.place[indx + 1]); + } + }; + } + + res = { place, reorder: [], place_new: [], blobs: [] }; + + for (let n = 0; n < place.length; n += 2) + res.reorder.push({ pos: place[n], len: place[n + 1], indx: [n] }); + + if (resort) + res.reorder.sort((a, b) => { return a.pos - b.pos; }); + + for (let n = 0; n < res.reorder.length - 1; n++) { + const curr = res.reorder[n], + next = res.reorder[n + 1]; + if (curr.pos + curr.len + kMinimalHttpGap > next.pos) { + curr.indx.push(...next.indx); + curr.len = next.pos + next.len - curr.pos; + res.reorder.splice(n + 1, 1); // remove segment + n--; + } + } + + res.reorder.forEach(elem => res.place_new.push(elem.pos, elem.len)); + + res.expectedSize = function(indx) { + return this.reorder[indx / 2].len; + }; + + res.addBuffer = function(indx, buf, o) { + const elem = this.reorder[indx / 2], + pos0 = elem.pos; + elem.indx.forEach(indx0 => { + this.blobs[indx0 / 2] = new DataView(buf, o + this.place[indx0] - pos0, this.place[indx0 + 1]); + }); + }; + + return res; + } + /** @summary read buffer(s) from the file * @return {Promise} with read buffers * @private */ @@ -124179,10 +126563,13 @@ class TFile { if ((this.fFileContent !== null) && !filename && (!this.fAcceptRanges || this.fFileContent.canExtract(place))) return this.fFileContent.extract(place); + const reorder = this.#checkNeedReorder(place); + if (reorder?.place_new) + place = reorder?.place_new; + let resolveFunc, rejectFunc; const file = this, first_block = (place[0] === 0) && (place.length === 2), - blobs = [], // array of requested segments promise = new Promise((resolve, reject) => { resolveFunc = resolve; rejectFunc = reject; @@ -124208,12 +126595,15 @@ class TFile { } } - function send_new_request(increment) { - if (increment) { + function send_new_request(arg) { + if (arg === 'noranges') { + file.fMaxRanges = 1; + last = Math.min(last, first + file.fMaxRanges * 2); + } else if (arg) { first = last; last = Math.min(first + file.fMaxRanges * 2, place.length); if (first >= place.length) - return resolveFunc(blobs); + return resolveFunc(reorder.blobs.length === 1 ? reorder.blobs[0] : reorder.blobs); } let fullurl = fileurl, ranges = 'bytes', totalsz = 0; @@ -124230,17 +126620,14 @@ class TFile { // when read first block, allow to read more - maybe ranges are not supported and full file content will be returned if (file.fAcceptRanges && first_block) - totalsz = Math.max(totalsz, 1e7); + totalsz = Math.max(totalsz, 1e5); - return createHttpRequest(fullurl, 'buf', read_callback, undefined, true).then(xhr => { + return createHttpRequest(fullurl, 'buf', read_callback, undefined, true, file.fTimeout).then(xhr => { if (file.fAcceptRanges) { xhr.setRequestHeader('Range', ranges); xhr.expected_size = Math.max(Math.round(1.1 * totalsz), totalsz + 200); // 200 if offset for the potential gzip } - if (file.fTimeout) - xhr.timeout = file.fTimeout; - if (isFunc(progress_callback) && isFunc(xhr.addEventListener)) { let sum1 = 0, sum2 = 0, sum_total = 0; for (let n = 1; n < place.length; n += 2) { @@ -124348,70 +126735,34 @@ class TFile { // if only single segment requested, return result as is if (last - first === 2) { - const b = new DataView(res); - if (place.length === 2) - return resolveFunc(b); - blobs.push(b); + reorder.addBuffer(first, res, 0); return send_new_request(true); } // object to access response data - const hdr = this.getResponseHeader('Content-Type'), - ismulti = isStr(hdr) && (hdr.indexOf('multipart') >= 0), - view = new DataView(res); - - if (!ismulti) { - // server may returns simple buffer, which combines all segments together - - const hdr_range = this.getResponseHeader('Content-Range'); - let segm_start = 0, segm_last = -1; - - if (isStr(hdr_range) && hdr_range.indexOf('bytes') >= 0) { - const parts = hdr_range.slice(hdr_range.indexOf('bytes') + 6).split(/[\s-/]+/); - if (parts.length === 3) { - segm_start = Number.parseInt(parts[0]); - segm_last = Number.parseInt(parts[1]); - if (!Number.isInteger(segm_start) || !Number.isInteger(segm_last) || (segm_start > segm_last)) { - segm_start = 0; - segm_last = -1; - } - } - } - - let canbe_single_segment = (segm_start <= segm_last); - for (let n = first; n < last; n += 2) { - if ((place[n] < segm_start) || (place[n] + place[n + 1] - 1 > segm_last)) - canbe_single_segment = false; - } - - if (canbe_single_segment) { - for (let n = first; n < last; n += 2) - blobs.push(new DataView(res, place[n] - segm_start, place[n + 1])); - return send_new_request(true); - } - - if ((file.fMaxRanges === 1) || !first) - return rejectFunc(Error('Server returns normal response when multipart was requested, disable multirange support')); + const hdr = this.getResponseHeader('Content-Type'); - file.fMaxRanges = 1; - last = Math.min(last, file.fMaxRanges * 2); - - return send_new_request(); + if (!isStr(hdr) || (hdr.indexOf('multipart') < 0)) { + console.error('Did not found multipart in content-type - fallback to single range request'); + return send_new_request('noranges'); } // multipart messages requires special handling const indx = hdr.indexOf('boundary='); - let boundary = '', n = first, o = 0, normal_order = true; - if (indx > 0) { - boundary = hdr.slice(indx + 9); - if ((boundary[0] === '"') && (boundary.at(-1) === '"')) - boundary = boundary.slice(1, boundary.length - 1); - boundary = '--' + boundary; - } else - console.error('Did not found boundary id in the response header'); + if (indx <= 0) { + console.error('Did not found boundary id in the response header - fallback to single range request'); + return send_new_request('noranges'); + } - while (n < last) { + let boundary = hdr.slice(indx + 9); + if ((boundary[0] === '"') && (boundary.at(-1) === '"')) + boundary = boundary.slice(1, boundary.length - 1); + boundary = '--' + boundary; + + const view = new DataView(res); + + for (let n = first, o = 0; n < last; n += 2) { let code1, code2 = view.getUint8(o), nline = 0, line = '', finish_header = false, segm_start = 0, segm_last = -1; @@ -124430,6 +126781,7 @@ class TFile { if (parts.length === 3) { segm_start = Number.parseInt(parts[0]); segm_last = Number.parseInt(parts[1]); + // TODO: check for consistency if (!Number.isInteger(segm_start) || !Number.isInteger(segm_last) || (segm_start > segm_last)) { segm_start = 0; segm_last = -1; @@ -124452,44 +126804,16 @@ class TFile { o++; } - if (!finish_header) - return rejectFunc(Error('Cannot decode header in multipart message')); - - if (segm_start > segm_last) { - // fall-back solution, believe that segments same as requested - blobs.push(new DataView(res, o, place[n + 1])); - o += place[n + 1]; - n += 2; - } else if (normal_order) { - const n0 = n; - while ((n < last) && (place[n] >= segm_start) && (place[n] + place[n + 1] - 1 <= segm_last)) { - blobs.push(new DataView(res, o + place[n] - segm_start, place[n + 1])); - n += 2; - } + const segm_size = segm_last - segm_start + 1; - if (n > n0) - o += (segm_last - segm_start + 1); - else - normal_order = false; + if (!finish_header || (segm_size <= 0) || (reorder.expectedSize(n) !== segm_size)) { + console.error('Failure decoding multirange header - fallback to single range request'); + return send_new_request('noranges'); } - if (!normal_order) { - // special situation when server reorder segments in the reply - let isany = false; - for (let n1 = n; n1 < last; n1 += 2) { - if ((place[n1] >= segm_start) && (place[n1] + place[n1 + 1] - 1 <= segm_last)) { - blobs[n1 / 2] = new DataView(res, o + place[n1] - segm_start, place[n1 + 1]); - isany = true; - } - } - if (!isany) - return rejectFunc(Error(`Provided fragment ${segm_start} - ${segm_last} out of requested multi-range request`)); - - while (blobs[n / 2]) - n += 2; + reorder.addBuffer(n, res, o); - o += (segm_last - segm_start + 1); - } + o += segm_size; } send_new_request(true); @@ -124788,10 +127112,14 @@ class TFile { // this part typically read from the header, no need to optimize return this.readBuffer([this.fBEGIN, Math.max(300, nbytes)]); }).then(blob3 => { - const buf3 = new TBuffer(blob3, 0, this); + const buf3 = new TBuffer(blob3, 0, this), + key = buf3.readTKey(); - // keep only title from TKey data - this.fTitle = buf3.readTKey().fTitle; + this.fTitle = key.fTitle; + if (this.fURL === kTmpFileName) { + this.fURL = this.fFullURL = key.fName; + this.assignFileName(key.fName); + } buf3.locate(this.fNbytesName); @@ -125012,9 +127340,8 @@ class TLocalFile extends TFile { this.fUseStampPar = false; this.fLocalFile = file; this.fEND = file.size; - this.fFullURL = file.name; - this.fURL = file.name; - this.fFileName = file.name; + this.fFullURL = this.fURL = file.name; + this.assignFileName(file.name); } /** @summary Open local file @@ -125071,22 +127398,21 @@ class TNodejsFile extends TFile { super(null); this.fUseStampPar = false; this.fEND = 0; - this.fFullURL = filename; - this.fURL = filename; - this.fFileName = filename; + this.fFullURL = this.fURL = filename; + this.assignFileName(filename); } /** @summary Open file in node.js * @return {Promise} after file keys are read */ async _open() { - return Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(fs => { + return import('fs').then(fs => { this.fs = fs; return new Promise((resolve, reject) => { - this.fs.open(this.fFileName, 'r', (status, fd) => { + this.fs.open(this.fFullURL, 'r', (status, fd) => { if (status) { console.log(status.message); - reject(Error(`Not possible to open ${this.fFileName} inside node.js`)); + reject(Error(`Not possible to open ${this.fFullURL} inside node.js`)); } else { const stats = this.fs.fstatSync(fd); this.fEND = stats.size; @@ -125108,7 +127434,7 @@ class TNodejsFile extends TFile { } if (!this.fs || !this.fd) { - reject(Error(`File is not opened ${this.fFileName}`)); + reject(Error(`File is not opened ${this.fFullURL}`)); return; } @@ -125151,6 +127477,7 @@ class FileProxy { getFileName() { return ''; } getFileSize() { return 0; } async readBuffer(/* pos, sz */) { return null; } + closeFile() {} } // class FileProxy @@ -125177,12 +127504,8 @@ class TProxyFile extends TFile { if (!res) return false; this.fEND = this.proxy.getFileSize(); - this.fFullURL = this.fURL = this.fFileName = this.proxy.getFileName(); - if (isStr(this.fFileName)) { - const p = this.fFileName.lastIndexOf('/'); - if ((p > 0) && (p < this.fFileName.length - 4)) - this.fFileName = this.fFileName.slice(p + 1); - } + this.fFullURL = this.fURL = this.proxy.getFileName(); + this.assignFileName(this.fURL); return this.readKeys(); }); } @@ -125194,7 +127517,7 @@ class TProxyFile extends TFile { return Promise.reject(Error(`Cannot access other file ${filename}`)); if (!this.proxy) - return Promise.reject(Error(`File is not opened ${this.fFileName}`)); + return Promise.reject(Error(`File is not opened ${this.fFullURL}`)); if (isFunc(this.proxy.readBuffers)) { return this.proxy.readBuffers(place).then(arr => { @@ -125211,6 +127534,15 @@ class TProxyFile extends TFile { return Promise.all(arr); } + /** @summary Fully cleanup TProxyFile data + * @private */ + delete() { + super.delete(); + if (isFunc(this.proxy?.closeFile)) + this.proxy.closeFile(); + delete this.proxy; + } + } // class TProxyFile @@ -125245,7 +127577,7 @@ function openFile(arg, opts) { file = new TProxyFile(arg); if (!file && isObject(arg) && (arg instanceof ArrayBuffer)) { - file = new TFile('localfile.root'); + file = new TFile(kTmpFileName); file.assignFileContent(arg); } @@ -126182,6 +128514,10 @@ class TDrawSelector extends TSelector { case 'dump': args.dump = true; break; + case 'dumpall': + args.dump = true; + args.numentries = this.getNumEntries(tree); + break; case 'staged': args.staged = true; break; @@ -126228,7 +128564,10 @@ class TDrawSelector extends TSelector { } if (harg === 'dump') args.dump = true; - else if (harg === 'elist') + else if (harg === 'dumpall') { + args.dump = true; + args.numentries = this.getNumEntries(tree); + } else if (harg === 'elist') args.dump_entries = true; else if (harg.indexOf('Graph') === 0) args.graph = true; @@ -126404,7 +128743,7 @@ class TDrawSelector extends TSelector { this.leaf = args.leaf; // branch object remains, therefore we need to copy fields to see them all - this.copy_fields = ((args.branch.fLeaves?.arr.length > 1) || args.branch.fBranches?.arr.length) && !args.leaf; + this.copy_fields = args.copy_fields ?? (((args.branch.fLeaves?.arr.length > 1) || args.branch.fBranches?.arr.length) && !args.leaf); this.addBranch(branch, 'br0', args.direct_branch); // add branch @@ -127100,10 +129439,11 @@ async function treeProcess(tree, selector, args) { case 'TLeafF': datakind = kFloat; break; case 'TLeafD': datakind = kDouble; break; case 'TLeafO': datakind = kBool; break; - case 'TLeafB': datakind = leaf.fIsUnsigned ? kUChar : kChar; break; + case 'TLeafB': datakind = leaf.fIsUnsigned ? kUChar : kChar$1; break; case 'TLeafS': datakind = leaf.fIsUnsigned ? kUShort : kShort; break; case 'TLeafI': datakind = leaf.fIsUnsigned ? kUInt : kInt; break; case 'TLeafL': datakind = leaf.fIsUnsigned ? kULong64 : kLong64; break; + case 'TLeafG': datakind = leaf.fIsUnsigned ? kULong : kLong; break; case 'TLeafC': datakind = kTString; break; default: return null; } @@ -127752,7 +130092,7 @@ async function treeProcess(tree, selector, args) { for (let k = 0; k < handle.arr.length; ++k) { const elem = handle.arr[k]; - if ((elem.type <= 0) || (elem.type >= kOffsetL) || (elem.type === kCharStar)) + if ((elem.type <= 0) || (elem.type >= kOffsetL) || (elem.type === kCharStar) || (elem.type === kFloat16) || (elem.type === kDouble32)) handle.process_arrays = false; } @@ -127770,7 +130110,7 @@ async function treeProcess(tree, selector, args) { elem.fArrayDim = 1; elem.fMaxIndex[0] = 10; // 10 if artificial number, will be replaced during reading - item.arrmember = createMemberStreamer(elem, handle.file); + item.arrmember = createMemberStreamer(elem, handle.file, true); } } } else @@ -162989,7 +165329,7 @@ async function makePDF(svg, args) { return res; }; - pr = Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(handle => { + pr = import('canvas').then(handle => { globalThis.Image = handle.Image; }); } @@ -163189,22 +165529,22 @@ const drawFuncs = { lst: [ { name: 'kind:Command', icon: 'img_execute', execute: true }, { name: 'TFolder', icon: 'img_folder', icon2: 'img_folderopen', noinspect: true, get_expand: () => import_h().then(h => h.folderHierarchy) }, { name: 'TTask', icon: 'img_task', get_expand: () => import_h().then(h => h.taskHierarchy), for_derived: true }, - { name: clTTree, icon: 'img_tree', get_expand: () => Promise.resolve().then(function () { return tree; }).then(h => h.treeHierarchy), draw: () => import_tree().then(h => h.drawTree), dflt: 'expand', opt: 'player;testio', shift: kInspect, pm: true }, + { name: clTTree, icon: 'img_tree', get_expand: () => Promise.resolve().then(function () { return tree; }).then(h => h.treeHierarchy), draw: () => import_tree().then(h => h.drawTree), dflt: 'expand', opt: 'player;testio', shift: kInspect, pm: true, transform: true }, { name: 'TNtuple', sameas: clTTree }, { name: 'TNtupleD', sameas: clTTree }, - { name: clTBranchFunc, icon: 'img_leaf_method', draw: () => import_tree().then(h => h.drawTree), opt: ';dump', noinspect: true }, - { name: /^TBranch/, icon: 'img_branch', draw: () => import_tree().then(h => h.drawTree), dflt: 'expand', opt: ';dump', ctrl: 'dump', shift: kInspect, ignore_online: true, always_draw: true }, - { name: /^TLeaf/, icon: 'img_leaf', noexpand: true, draw: () => import_tree().then(h => h.drawTree), opt: ';dump', ctrl: 'dump', ignore_online: true, always_draw: true }, - { name: 'ROOT::RNTuple', icon: 'img_tree', get_expand: () => Promise.resolve().then(function () { return rntuple; }).then(h => h.tupleHierarchy), draw: () => Promise.resolve().then(function () { return RNTuple; }).then(h => h.drawRNTuple), dflt: 'expand', pm: true }, - { name: 'ROOT::RNTupleField', icon: 'img_leaf', draw: () => Promise.resolve().then(function () { return RNTuple; }).then(h => h.drawRNTuple), opt: ';dump', ctrl: 'dump', shift: kInspect, ignore_online: true, always_draw: true }, + { name: clTBranchFunc, icon: 'img_leaf_method', draw: () => import_tree().then(h => h.drawTree), opt: ';dump;dumpall', noinspect: true, transform: true }, + { name: /^TBranch/, icon: 'img_branch', draw: () => import_tree().then(h => h.drawTree), dflt: 'expand', opt: ';dump;dumpall', ctrl: 'dump', shift: kInspect, ignore_online: true, always_draw: true, transform: true }, + { name: /^TLeaf/, icon: 'img_leaf', noexpand: true, draw: () => import_tree().then(h => h.drawTree), opt: ';dump;dumpall', ctrl: 'dump', ignore_online: true, always_draw: true, transform: true }, + { name: 'ROOT::RNTuple', icon: 'img_tree', get_expand: () => Promise.resolve().then(function () { return rntuple; }).then(h => h.tupleHierarchy), draw: () => Promise.resolve().then(function () { return RNTuple; }).then(h => h.drawRNTuple), dflt: 'expand', pm: true, transform: true }, + { name: 'ROOT::RNTupleField', icon: 'img_leaf', draw: () => Promise.resolve().then(function () { return RNTuple; }).then(h => h.drawRNTuple), opt: ';dump;dumpall', ctrl: 'dump', shift: kInspect, ignore_online: true, always_draw: true, transform: true }, { name: clTList, icon: 'img_list', draw: () => import_h().then(h => h.drawList), get_expand: () => import_h().then(h => h.listHierarchy), dflt: 'expand' }, { name: clTHashList, sameas: clTList }, { name: clTObjArray, sameas: clTList }, { name: clTClonesArray, sameas: clTList }, { name: clTMap, sameas: clTList }, { name: clTColor, icon: 'img_color' }, - { name: clTFile, icon: 'img_file', noinspect: true }, - { name: 'TMemFile', icon: 'img_file', noinspect: true }, + { name: clTFile, icon: 'img_file', noinspect: true, pm: true }, + { name: 'TMemFile', icon: 'img_file', noinspect: true, pm: true }, { name: clTStyle, icon: 'img_question', noexpand: true }, { name: 'Session', icon: 'img_globe' }, { name: 'kind:TopFolder', icon: 'img_base' }, @@ -163228,19 +165568,28 @@ const drawFuncs = { lst: [ /** @summary Register draw function for the class - * @desc List of supported draw options could be provided, separated with ';' * @param {object} args - arguments - * @param {string|regexp} args.name - class name or regexp pattern + * @param {string|regexp} args.name - class name or regexp pattern or '*' * @param {function} [args.func] - draw function + * @param {string} [args.sameas] - let behave same as specified class * @param {function} [args.draw] - async function to load draw function * @param {function} [args.class] - async function to load painter class with static draw function * @param {boolean} [args.direct] - if true, function is just Redraw() method of ObjectPainter * @param {string} [args.opt] - list of supported draw options (separated with semicolon) like 'col;scat;' * @param {string} [args.icon] - icon name shown for the class in hierarchy browser * @param {string} [args.draw_field] - draw only data member from object, like fHistogram + * @param {string} [args.noinspect] - disable inspect + * @param {string} [args.noexpand] - disable expand + * @param {string} [args.pm] - always show plus or minus sign even when no child items exists + * @desc List of supported draw options could be provided, separated with ';' + * If args.name parameter is '*', function will be invoked before object drawing. + * If such function does not return value - normal drawing will be continued. * @protected */ function addDrawFunc(args) { - drawFuncs.lst.push(args); + if (args?.name === '*') + internals._alt_draw = isFunc(args.func) ? args.func : null; + else + drawFuncs.lst.push(args); return args; } @@ -163451,6 +165800,12 @@ async function draw(dom, obj, opt) { if (handle.draw_field && obj[handle.draw_field]) return draw(dom, obj[handle.draw_field], opt || handle.draw_field_opt); + if (internals._alt_draw && !handle.transform) { + const v = internals._alt_draw(dom, obj, opt); + if (v) + return v; + } + if (!canDrawHandle(handle)) { if (opt && (opt.indexOf('same') >= 0)) { const main_painter = getElementMainPainter(dom); @@ -163755,7 +166110,7 @@ async function makeImage(args) { if (!mainsvg.attr('width') && !mainsvg.attr('height')) mainsvg.attr('width', args.width).attr('height', args.height); - if (style_filter) + if (style_filter && (style_filter !== 'none')) mainsvg.style('filter', style_filter); function clear_element() { @@ -164388,7 +166743,11 @@ function objectHierarchy(top, obj, args = undefined) { } } } - } else if ((typeof fld === 'number') || (typeof fld === 'boolean') || (typeof fld === 'bigint')) { + } else if (typeof fld === 'bigint') { + simple = true; + item._value = fld.toString() + 'n'; + item._vclass = cssValueNum; + } else if ((typeof fld === 'number') || (typeof fld === 'boolean')) { simple = true; if (key === 'fBits') item._value = '0x' + fld.toString(16); @@ -164588,7 +166947,6 @@ function parseAsArray(val) { nbr--; break; } - // eslint-disable-next-line no-fallthrough case ',': if (nbr === 0) { let sub = val.substring(last, indx).trim(); @@ -165248,6 +167606,9 @@ class HierarchyPainter extends BasePainter { if (!element_title) element_title = element_name; + if (hitem._filter) + element_name += ' *'; + d3a.attr('title', element_title) .text(element_name + ('_value' in hitem ? ':' : '')) .style('background', hitem._background ? hitem._background : null); @@ -165267,6 +167628,8 @@ class HierarchyPainter extends BasePainter { for (let i = 0; i < hitem._childs.length; ++i) { const chld = hitem._childs[i]; chld._parent = hitem; + if (hitem._filter && chld._name && chld._name.indexOf(hitem._filter) < 0) + continue; if (!this.addItemHtml(chld, d3chlds, i)) break; // if too many items, skip rest } @@ -165696,21 +168059,21 @@ class HierarchyPainter extends BasePainter { /** @summary alternative context menu, used in the object inspector * @private */ direct_contextmenu(evnt, elem) { - evnt.preventDefault(); const itemname = select(elem.parentNode.parentNode).attr('item'), hitem = this.findItem(itemname); - if (!hitem) + if (!hitem || !isFunc(this.fill_context)) return; - if (isFunc(this.fill_context)) { - createMenu(evnt, this).then(menu => { - this.fill_context(menu, hitem); - if (menu.size() > 0) { - menu.tree_node = elem.parentNode; - menu.show(); - } - }); - } + evnt.preventDefault(); + evnt.stopPropagation(); + + createMenu(evnt, this).then(menu => { + this.fill_context(menu, hitem); + if (menu.size() > 0) { + menu.tree_node = elem.parentNode; + menu.show(); + } + }); } /** @summary Fills settings menu items @@ -165756,11 +168119,12 @@ class HierarchyPainter extends BasePainter { /** @summary Handle context menu in the hierarchy * @private */ tree_contextmenu(evnt, elem) { - evnt.preventDefault(); const itemname = select(elem.parentNode.parentNode).attr('item'), hitem = this.findItem(itemname); if (!hitem) return; + evnt.preventDefault(); + evnt.stopPropagation(); const onlineprop = this.getOnlineProp(itemname), fileprop = this.getFileProp(itemname); @@ -165930,6 +168294,15 @@ class HierarchyPainter extends BasePainter { if (hitem._childs === undefined) menu.add('Expand', () => this.expandItem(itemname), 'Expand content of object'); else { + if (sett.handle?.pm || (hitem._childs.length > 25)) { + menu.add('Filter...', () => menu.input('Enter items to select', hitem._filter, f => { + const changed = hitem._filter !== f; + hitem._filter = f; + if (changed) + this.updateTreeNode(hitem); + }), 'Filter out items based on input pattern'); + } + menu.add('Unexpand', () => { hitem._more = true; delete hitem._childs; @@ -166107,10 +168480,8 @@ class HierarchyPainter extends BasePainter { if (use_dflt_opt && !drawopt && handle?.dflt && (handle.dflt !== kExpand)) drawopt = handle.dflt; - if (dom) { - const func = updating ? redraw : draw; - return func(dom, obj, drawopt).then(p => complete(p)).catch(err => complete(null, err)); - } + if (dom) + return (updating ? redraw : draw)(dom, obj, drawopt).then(p => complete(p)).catch(err => complete(null, err)); let did_activate = false; const arr = []; @@ -166155,8 +168526,8 @@ class HierarchyPainter extends BasePainter { mdi.activateFrame(frame); return draw(frame, obj, drawopt) - .then(p => complete(p)) - .catch(err => complete(null, err)); + .then(p => complete(p)) + .catch(err => complete(null, err)); }); }); } @@ -166718,8 +169089,9 @@ class HierarchyPainter extends BasePainter { if ((hitem._more === false) || (!hitem._parent && hitem._childs)) return; - if (hitem._childs && hitem._isopen) { - hitem._isopen = false; + // for the file expand always just toggle isopen flag + if (hitem._childs && (hitem._isopen || hitem._file)) { + hitem._isopen = !hitem._isopen; if (!silent) this.updateTreeNode(hitem, d3cont); return; @@ -166873,12 +169245,15 @@ class HierarchyPainter extends BasePainter { } return this.refreshHtml(); - }).catch(() => { + }).catch(err => { // make CORS warning - if (isBatchMode()) - console.error(`Fail to open ${msg} - check CORS headers`); - else if (!select('#gui_fileCORS').style('background', 'red').empty()) - setTimeout(() => select('#gui_fileCORS').style('background', ''), 5000); + const elem = isBatchMode() ? null : select('#gui_fileCORS'); + if (!elem || elem.empty()) + console.error(`Fail to open ${msg} - ${err?.message ?? 'check CORS headers'}`); + else { + elem.style('background', 'red'); + setTimeout(() => elem.style('background', ''), 5000); + } return false; }).finally(() => showProgress()); } @@ -167113,7 +169488,7 @@ class HierarchyPainter extends BasePainter { handleAfterRequest(findFunction(item._after_request)); // v6 support } else handleAfterRequest(draw_handle?.after_request); - }, undefined, true).then(xhr => { + }, undefined, true, settings.ServerTimeout).then(xhr => { itemreq = xhr; xhr.send(null); }); @@ -167429,7 +169804,7 @@ class HierarchyPainter extends BasePainter { } // check that we can found frame where drawing should be done - if (!document.getElementById(this.disp_frameid)) + if (!this.disp_frameid || !document.getElementById(this.disp_frameid)) return null; if (isBatchMode()) @@ -167629,8 +170004,8 @@ class HierarchyPainter extends BasePainter { if (!browser_configured && (browser.screenWidth <= 640)) browser_kind = 'float'; - this.no_select = getOption('noselect'); - this.top_info = getOption('info'); + this.no_select ??= getOption('noselect'); + this.top_info ??= getOption('info'); if (getOption('files_monitoring') !== null) this.files_monitoring = true; @@ -167890,7 +170265,7 @@ class HierarchyPainter extends BasePainter { ''; } else if (!this.no_select) { const myDiv = select('#' + this.gui_div), - files = myDiv.attr('files') || '../files/hsimple.root', + files = myDiv.attr('files') || 'https://root.cern/js/files/hsimple.root', path = decodeUrl().get('path') || myDiv.attr('path') || '', arrFiles = files.split(';'); @@ -167924,6 +170299,7 @@ class HierarchyPainter extends BasePainter { const title_elem = this.brlayout.setBrowserTitle(this.top_info || (this.is_online ? 'ROOT online server' : 'Read a ROOT file')); title_elem?.on('contextmenu', evnt => { evnt.preventDefault(); + evnt.stopPropagation(); createMenu(evnt).then(menu => { this.fillSettingsMenu(menu, true); menu.show(); @@ -168251,6 +170627,12 @@ function readStyleFromURL(url) { if (d.has('prefer_saved_points')) settings.PreferSavedPoints = true; + if (d.has('tmout')) + settings.ServerTimeout = parseFloat(d.get('tmout')); + + if (d.has('ftmout')) + settings.FilesTimeout = parseFloat(d.get('ftmout')); + const tf1_style = d.get('tf1'); if (tf1_style === 'curve') settings.FuncAsCurve = true; @@ -168442,7 +170824,7 @@ async function buildGUI(gui_element, gui_kind = '') { myDiv.html(''); // clear element - const d = decodeUrl(), getSize = name => { + const nb = (gui_kind === 'notebook'), d = decodeUrl(), getSize = name => { const res = d.has(name) ? d.get(name).split('x') : []; if (res.length !== 2) return null; @@ -168457,7 +170839,7 @@ async function buildGUI(gui_element, gui_kind = '') { else if ((gui_kind === 'nobrowser') || d.has('nobrowser') || (myDiv.attr('nobrowser') && myDiv.attr('nobrowser') !== 'false')) nobrowser = true; - if (myDiv.attr('ignoreurl') === 'true') + if (nb || (myDiv.attr('ignoreurl') === 'true')) settings.IgnoreUrlOptions = true; readStyleFromURL(); @@ -168488,6 +170870,10 @@ async function buildGUI(gui_element, gui_kind = '') { if (drawing || isBatchMode()) hpainter.exclude_browser = true; hpainter.start_without_browser = nobrowser; + if (nb) { + hpainter.no_select = true; + hpainter.top_info = 'ROOT notebook'; + } return hpainter.startGUI(myDiv).then(() => { if (!nobrowser) @@ -168505,13 +170891,6 @@ async function buildGUI(gui_element, gui_kind = '') { }).then(() => hpainter); } -var _rollup_plugin_ignore_empty_module_placeholder = {}; - -var _rollup_plugin_ignore_empty_module_placeholder$1 = /*#__PURE__*/Object.freeze({ -__proto__: null, -default: _rollup_plugin_ignore_empty_module_placeholder -}); - /** @summary Draw TEllipse * @private */ function drawEllipse() { @@ -168893,6 +171272,12 @@ async function drawTreeDrawResult(dom, obj, opt) { if (!typ || !isStr(typ)) return Promise.reject(Error('Object without type cannot be draw with TTree')); + if (internals._alt_draw) { + const v = internals._alt_draw(dom, obj, opt); + if (v) + return v; + } + if (typ.indexOf(clTH1) === 0) return TH1Painter.draw(dom, obj, opt); if (typ.indexOf(clTH2) === 0) @@ -169345,6 +171730,11 @@ class TTextPainter extends ObjectPainter { pp = this.getPadPainter(), fp = this.getFramePainter(), is_url = text.fName.startsWith('http://') || text.fName.startsWith('https://'); + + // special handling of dummy frame painter + if (fp?.getDrawDom() === null) + return this; + let fact = 1, use_frame = false; this.createAttText({ attr: text }); @@ -169828,7 +172218,11 @@ let THStackPainter$2 = class THStackPainter extends ObjectPainter { o.auto += ' ' + f; }); - o.pads = d.check('PADS'); + if (d.check('PADS', true)) { + o.pads = true; + o.pads_columns = d.partAsInt(); + } + if (o.pads) o.nostack = true; @@ -170045,7 +172439,12 @@ let THStackPainter$2 = class THStackPainter extends ObjectPainter { if (o.pads) { pr = ensureTCanvas(this, false).then(() => { pad_painter = this.getPadPainter(); - return pad_painter.divide(o.nhist, 0, true); + let nx = o.nhist, ny = 0; + if (o.pads_columns) { + nx = o.pads_columns; + ny = Math.ceil(o.nhist / nx); + } + return pad_painter.divide(nx, ny, true); }); } else { if (!o.nostack) @@ -174052,6 +176451,7 @@ let TMultiGraphPainter$2 = class TMultiGraphPainter extends ObjectPainter { #auto; // extra options for auto colors #is3d; // if 3d drawing #pads; // pads draw option + #pads_columns; // number pads columns /** @summary Create painter * @param {object|string} dom - DOM element for drawing or element id @@ -174345,7 +176745,9 @@ let TMultiGraphPainter$2 = class TMultiGraphPainter extends ObjectPainter { this.#is3d = d.check('3D'); this.#auto = ''; - this.#pads = d.check('PADS'); + this.#pads = d.check('PADS', true); + if (this.#pads) + this.#pads_columns = d.partAsInt(); ['PFC', 'PLC', 'PMC'].forEach(f => { if (d.check(f)) this.#auto += ' ' + f; @@ -174365,7 +176767,12 @@ let TMultiGraphPainter$2 = class TMultiGraphPainter extends ObjectPainter { if (this.#pads) { promise = ensureTCanvas(this, false).then(() => { pad_painter = this.getPadPainter(); - return pad_painter.divide(mgraph.fGraphs.arr.length, 0, true); + let nx = mgraph.fGraphs.arr.length, ny = 0; + if (this.#pads_columns) { + ny = Math.ceil(nx / this.#pads_columns); + nx = this.#pads_columns; + } + return pad_painter.divide(nx, ny, true); }); } else if (d.check('A') || !this.getMainPainter()) { const histo = this.scanGraphsRange(mgraph.fGraphs, mgraph.fHistogram, this.getPadPainter()?.getRootPad(true)); @@ -176511,7 +178918,7 @@ class TGaxisPainter extends TAxisPainter { const res = function(v) { return res.toGraph(v); }; res._func = func; res._domain = [smin, smax]; - res._scale = logbase ? log().base(logbase) : linear(); + res._scale = logbase ? log$1().base(logbase) : linear(); res._scale.domain(res._domain).range([0, 100]); res.eval = function(v) { try { @@ -176827,7 +179234,7 @@ class TASImagePainter extends ObjectPainter { const z = this.getImageZoomRange(fp, obj.fConstRatio, obj.fWidth, obj.fHeight), pr = isNodeJs() - ? Promise.resolve().then(function () { return _rollup_plugin_ignore_empty_module_placeholder$1; }).then(h => h.default.createCanvas(z.xmax - z.xmin, z.ymax - z.ymin)) + ? import('canvas').then(h => h.default.createCanvas(z.xmax - z.xmin, z.ymax - z.ymin)) : new Promise(resolveFunc => { const c = document.createElement('canvas'); c.width = z.xmax - z.xmin; @@ -177184,7 +179591,40 @@ __proto__: null, TASImagePainter: TASImagePainter }); -const LITTLE_ENDIAN = true; +// ENTupleColumnType - supported column types + +const kBit = 0x00, + kByte = 0x01, + kChar = 0x02, + kInt8 = 0x03, + kUInt8 = 0x04, + kInt16 = 0x05, + kUInt16 = 0x06, + kInt32 = 0x07, + kUInt32 = 0x08, + kInt64 = 0x09, + kUInt64 = 0x0A, + kReal16 = 0x0B, + kReal32 = 0x0C, + kReal64 = 0x0D, + kIndex32 = 0x0E, + kIndex64 = 0x0F, + kSwitch = 0x10, + kSplitInt16 = 0x11, + kSplitUInt16 = 0x12, + kSplitInt32 = 0x13, + kSplitUInt32 = 0x14, + kSplitInt64 = 0x15, + kSplitUInt64 = 0x16, + kSplitReal16 = 0x17, + kSplitReal32 = 0x18, + kSplitReal64 = 0x19, + kSplitIndex32 = 0x1A, + kSplitIndex64 = 0x1B, + kReal32Trunc = 0x1C, + kReal32Quant = 0x1D, + LITTLE_ENDIAN = true; + class RBufferReader { constructor(buffer) { @@ -177296,192 +179736,99 @@ class RBufferReader { } -const ENTupleColumnType = { - kBit: 0x00, - kByte: 0x01, - kChar: 0x02, - kInt8: 0x03, - kUInt8: 0x04, - kInt16: 0x05, - kUInt16: 0x06, - kInt32: 0x07, - kUInt32: 0x08, - kInt64: 0x09, - kUInt64: 0x0A, - kReal16: 0x0B, - kReal32: 0x0C, - kReal64: 0x0D, - kIndex32: 0x0E, - kIndex64: 0x0F, - kSplitInt16: 0x11, - kSplitUInt16: 0x12, - kSplitInt32: 0x13, - kSplitUInt32: 0x14, - kSplitInt64: 0x15, - kSplitUInt64: 0x16, - kSplitReal16: 0x17, - kSplitReal32: 0x18, - kSplitReal64: 0x19, - kSplitIndex32: 0x1A, - kSplitIndex64: 0x1B}; - - -/** - * @summary Rearrange bytes from split format to normal format (row-wise) for decoding - */ -function recontructUnsplitBuffer(blob, columnDescriptor) { - const { coltype } = columnDescriptor; - - if ( - coltype === ENTupleColumnType.kSplitUInt16 || - coltype === ENTupleColumnType.kSplitUInt32 || - coltype === ENTupleColumnType.kSplitUInt64 || - coltype === ENTupleColumnType.kSplitReal16 || - coltype === ENTupleColumnType.kSplitReal32 || - coltype === ENTupleColumnType.kSplitReal64 || - coltype === ENTupleColumnType.kSplitIndex32 || - coltype === ENTupleColumnType.kSplitIndex64 || - coltype === ENTupleColumnType.kSplitInt16 || - coltype === ENTupleColumnType.kSplitInt32 || - coltype === ENTupleColumnType.kSplitInt64 - ) { - // Determine byte size based on column type - let byteSize; - switch (coltype) { - case ENTupleColumnType.kSplitReal64: - case ENTupleColumnType.kSplitInt64: - case ENTupleColumnType.kSplitUInt64: - case ENTupleColumnType.kSplitIndex64: - byteSize = 8; - break; - case ENTupleColumnType.kSplitReal32: - case ENTupleColumnType.kSplitInt32: - case ENTupleColumnType.kSplitIndex32: - case ENTupleColumnType.kSplitUInt32: - byteSize = 4; - break; - case ENTupleColumnType.kSplitInt16: - case ENTupleColumnType.kSplitUInt16: - case ENTupleColumnType.kSplitReal16: - byteSize = 2; - break; - default: - throw new Error(`Unsupported split coltype: ${coltype} (0x${coltype.toString(16).padStart(2, '0')})`); - } - const splitView = new DataView(blob.buffer, blob.byteOffset, blob.byteLength), - count = blob.byteLength / byteSize, - outBuffer = new ArrayBuffer(blob.byteLength), - outBytes = new Uint8Array(outBuffer); +/** @summary Rearrange bytes from split format to normal format (row-wise) for decoding + * @private */ +function recontructUnsplitBuffer(view, coltype) { + // Determine byte size based on column type + let byteSize; + switch (coltype) { + case kSplitReal64: + case kSplitInt64: + case kSplitUInt64: + case kSplitIndex64: + byteSize = 8; + break; + case kSplitReal32: + case kSplitInt32: + case kSplitIndex32: + case kSplitUInt32: + byteSize = 4; + break; + case kSplitInt16: + case kSplitUInt16: + case kSplitReal16: + byteSize = 2; + break; + default: + return view; + } - for (let i = 0; i < count; ++i) { - for (let b = 0; b < byteSize; ++b) { - const splitIndex = b * count + i, - byte = splitView.getUint8(splitIndex), - writeIndex = i * byteSize + b; - outBytes[writeIndex] = byte; - } - } + const count = view.byteLength / byteSize, + outBuffer = new ArrayBuffer(view.byteLength), + outView = new DataView(outBuffer); - // Return updated blob and remapped coltype - const newBlob = outBuffer; - let newColtype; - switch (coltype) { - case ENTupleColumnType.kSplitUInt16: - newColtype = ENTupleColumnType.kUInt16; - break; - case ENTupleColumnType.kSplitUInt32: - newColtype = ENTupleColumnType.kUInt32; - break; - case ENTupleColumnType.kSplitUInt64: - newColtype = ENTupleColumnType.kUInt64; - break; - case ENTupleColumnType.kSplitIndex32: - newColtype = ENTupleColumnType.kIndex32; - break; - case ENTupleColumnType.kSplitIndex64: - newColtype = ENTupleColumnType.kIndex64; - break; - case ENTupleColumnType.kSplitReal16: - newColtype = ENTupleColumnType.kReal16; - break; - case ENTupleColumnType.kSplitReal32: - newColtype = ENTupleColumnType.kReal32; - break; - case ENTupleColumnType.kSplitReal64: - newColtype = ENTupleColumnType.kReal64; - break; - case ENTupleColumnType.kSplitInt16: - newColtype = ENTupleColumnType.kInt16; - break; - case ENTupleColumnType.kSplitInt32: - newColtype = ENTupleColumnType.kInt32; - break; - case ENTupleColumnType.kSplitInt64: - newColtype = ENTupleColumnType.kInt64; - break; - default: - throw new Error(`Unsupported split coltype for reassembly: ${coltype}`); + for (let i = 0; i < count; ++i) { + for (let b = 0; b < byteSize; ++b) { + const splitIndex = b * count + i, + byte = view.getUint8(splitIndex), + writeIndex = i * byteSize + b; + outView.setUint8(writeIndex, byte); } - - return { blob: newBlob, coltype: newColtype }; } - // If no split type, return original blob and coltype - return { blob, coltype }; + return outView; } +/** @summary Decode a 32 bit intex buffer + * @private */ +function decodeIndex32(view) { + for (let o = 0, prev = 0; o < view.byteLength; o += 4) { + const v = prev + view.getInt32(o, LITTLE_ENDIAN); + view.setInt32(o, v, LITTLE_ENDIAN); + prev = v; + } +} -/** - * @summary Decode a reconstructed index buffer (32- or 64-bit deltas to absolute indices) - */ -function DecodeDeltaIndex(blob, coltype) { - let deltas, result; - - if (coltype === ENTupleColumnType.kIndex32) { - deltas = new Int32Array(blob.buffer || blob, blob.byteOffset || 0, blob.byteLength / 4); - result = new Int32Array(deltas.length); - } else if (coltype === ENTupleColumnType.kIndex64) { - deltas = new BigInt64Array(blob.buffer || blob, blob.byteOffset || 0, blob.byteLength / 8); - result = new BigInt64Array(deltas.length); - } else - throw new Error(`DecodeDeltaIndex: unsupported column type ${coltype}`); +/** @summary Decode a 64 bit intex buffer + * @private */ +function decodeIndex64(view, shift) { + for (let o = 0, prev = 0n; o < view.byteLength; o += (8 + shift)) { + const v = prev + view.getBigInt64(o, LITTLE_ENDIAN); + view.setBigInt64(o, v, LITTLE_ENDIAN); + prev = v; + } +} - if (deltas.length > 0) - result[0] = deltas[0]; - for (let i = 1; i < deltas.length; ++i) - result[i] = result[i - 1] + deltas[i]; - return { blob: result, coltype }; +/** @summary Decode a reconstructed 16bit signed integer buffer using ZigZag encoding + * @private */ +function decodeZigzag16(view) { + for (let o = 0; o < view.byteLength; o += 2) { + const x = view.getUint16(o, LITTLE_ENDIAN); + view.setInt16(o, (x >>> 1) ^ (-(x & 1)), LITTLE_ENDIAN); + } } -/** - * @summary Decode a reconstructed signed integer buffer using ZigZag encoding - */ -function decodeZigzag(blob, coltype) { - let zigzag, result; - - if (coltype === ENTupleColumnType.kInt16) { - zigzag = new Uint16Array(blob.buffer || blob, blob.byteOffset || 0, blob.byteLength / 2); - result = new Int16Array(zigzag.length); - } else if (coltype === ENTupleColumnType.kInt32) { - zigzag = new Uint32Array(blob.buffer || blob, blob.byteOffset || 0, blob.byteLength / 4); - result = new Int32Array(zigzag.length); - } else if (coltype === ENTupleColumnType.kInt64) { - zigzag = new BigUint64Array(blob.buffer || blob, blob.byteOffset || 0, blob.byteLength / 8); - result = new BigInt64Array(zigzag.length); - } else - throw new Error(`decodeZigzag: unsupported column type ${coltype}`); - - for (let i = 0; i < zigzag.length; ++i) { - // ZigZag decode: (x >>> 1) ^ (-(x & 1)) - const x = zigzag[i]; - result[i] = (x >>> 1) ^ (-(x & 1)); +/** @summary Decode a reconstructed 32bit signed integer buffer using ZigZag encoding + * @private */ +function decodeZigzag32(view) { + for (let o = 0; o < view.byteLength; o += 4) { + const x = view.getUint32(o, LITTLE_ENDIAN); + view.setInt32(o, (x >>> 1) ^ (-(x & 1)), LITTLE_ENDIAN); } +} - return { blob: result, coltype }; +/** @summary Decode a reconstructed 64bit signed integer buffer using ZigZag encoding + * @private */ +function decodeZigzag64(view) { + for (let o = 0; o < view.byteLength; o += 8) { + const x = view.getUint64(o, LITTLE_ENDIAN); + view.setInt64(o, (x >>> 1) ^ (-(x & 1)), LITTLE_ENDIAN); + } } + // Envelope Types // TODO: Define usage logic for envelope types in future // const kEnvelopeTypeHeader = 0x01, @@ -177504,13 +179851,9 @@ class RNTupleDescriptorBuilder { return; const reader = new RBufferReader(header_blob), - payloadStart = reader.offset, // Read the envelope metadata - { - envelopeLength - } = this._readEnvelopeMetadata(reader), - + { envelopeLength } = this._readEnvelopeMetadata(reader), // Seek to end of envelope to get checksum checksumPos = payloadStart + envelopeLength - 8, currentPos = reader.offset; @@ -177541,7 +179884,6 @@ class RNTupleDescriptorBuilder { // Read the envelope metadata this._readEnvelopeMetadata(reader); - // Feature flag(32 bits) this._readFeatureFlags(reader); // Header checksum (64-bit xxhash3) @@ -177550,7 +179892,6 @@ class RNTupleDescriptorBuilder { throw new Error('RNTuple corrupted: header checksum does not match footer checksum.'); const schemaExtensionSize = reader.readS64(); - if (schemaExtensionSize < 0) throw new Error('Schema extension frame is not a record frame, which is unexpected.'); @@ -177561,10 +179902,8 @@ class RNTupleDescriptorBuilder { this._readClusterGroups(reader); } - _readEnvelopeMetadata(reader) { const typeAndLength = reader.readU64(), - // Envelope metadata // The 16 bits are the envelope type ID, and the 48 bits are the envelope length envelopeType = Number(typeAndLength & 0xFFFFn), @@ -177590,7 +179929,6 @@ class RNTupleDescriptorBuilder { this.extraTypeInfo = (this.extraTypeInfo || []).concat(newExtra); } - _readFeatureFlags(reader) { this.featureFlags = []; while (true) { @@ -177610,14 +179948,12 @@ class RNTupleDescriptorBuilder { fieldListSize = reader.readS64(), // signed 64-bit fieldListIsList = fieldListSize < 0; - if (!fieldListIsList) throw new Error('Field list frame is not a list frame, which is required.'); const fieldListCount = reader.readU32(), // number of field entries - // List frame: list of field record frames + fieldDescriptors = []; // List frame: list of field record frames - fieldDescriptors = []; for (let i = 0; i < fieldListCount; ++i) { const recordStart = BigInt(reader.offset), fieldRecordSize = reader.readS64(), @@ -177626,7 +179962,6 @@ class RNTupleDescriptorBuilder { parentFieldId = reader.readU32(), structRole = reader.readU16(), flags = reader.readU16(), - fieldName = reader.readString(), typeName = reader.readString(), typeAlias = reader.readString(), @@ -177644,7 +179979,6 @@ class RNTupleDescriptorBuilder { if (flags & kFlagHasTypeChecksum) checksum = reader.readU32(); - fieldDescriptors.push({ fieldVersion, typeVersion, @@ -177693,7 +180027,6 @@ class RNTupleDescriptorBuilder { maxValue = reader.readF64(); } - const column = { coltype, bitsOnStorage, @@ -177718,6 +180051,7 @@ class RNTupleDescriptorBuilder { reader.seek(Number(startOffset - columnListSize)); return columnDescriptors; } + _readAliasColumn(reader) { const startOffset = BigInt(reader.offset), aliasColumnListSize = reader.readS64(), @@ -177740,6 +180074,7 @@ class RNTupleDescriptorBuilder { reader.seek(Number(startOffset - aliasColumnListSize)); return aliasColumns; } + _readExtraTypeInformation(reader) { const startOffset = BigInt(reader.offset), extraTypeInfoListSize = reader.readS64(), @@ -177749,7 +180084,6 @@ class RNTupleDescriptorBuilder { throw new Error('Extra type info frame is not a list frame, which is required.'); const entryCount = reader.readU32(), - extraTypeInfo = []; for (let i = 0; i < entryCount; ++i) { const recordStart = BigInt(reader.offset), @@ -177765,6 +180099,7 @@ class RNTupleDescriptorBuilder { reader.seek(Number(startOffset - extraTypeInfoListSize)); return extraTypeInfo; } + _readClusterGroups(reader) { const startOffset = BigInt(reader.offset), clusterGroupListSize = reader.readS64(), @@ -177772,9 +180107,8 @@ class RNTupleDescriptorBuilder { if (!isList) throw new Error('Cluster group frame is not a list frame'); - const groupCount = reader.readU32(), - - clusterGroups = []; + const groupCount = reader.readU32(); + this.clusterGroups = []; for (let i = 0; i < groupCount; ++i) { const recordStart = BigInt(reader.offset), @@ -177783,24 +180117,12 @@ class RNTupleDescriptorBuilder { entrySpan = reader.readU64(), numClusters = reader.readU32(), pageListLength = reader.readU64(), - - - // Locator method to get the page list locator offset - pageListLocator = this._readLocator(reader), - - - group = { - minEntry, - entrySpan, - numClusters, - pageListLocator, - pageListLength - }; - clusterGroups.push(group); + // Locator method to get the page list locator offset + pageListLocator = this._readLocator(reader); + this.clusterGroups.push({ minEntry, entrySpan, numClusters, pageListLocator, pageListLength }); reader.seek(Number(recordStart + clusterRecordSize)); } reader.seek(Number(startOffset - clusterGroupListSize)); - this.clusterGroups = clusterGroups; } _readLocator(reader) { @@ -177809,11 +180131,9 @@ class RNTupleDescriptorBuilder { throw new Error('Non-standard locators (T=1) not supported yet'); const size = sizeAndType, offset = reader.readU64(); // 8 bytes: offset - return { - size, - offset - }; + return { size, offset }; } + deserializePageList(page_list_blob) { if (!page_list_blob) throw new Error('deserializePageList: received an invalid or empty page list blob'); @@ -177830,39 +180150,34 @@ class RNTupleDescriptorBuilder { clusterSummaryListSize = reader.readS64(); if (clusterSummaryListSize >= 0) throw new Error('Expected a list frame for cluster summaries'); - const clusterSummaryCount = reader.readU32(), - - clusterSummaries = []; + const clusterSummaryCount = reader.readU32(); + this.clusterSummaries = []; for (let i = 0; i < clusterSummaryCount; ++i) { const recordStart = BigInt(reader.offset), clusterSummaryRecordSize = reader.readS64(), firstEntry = reader.readU64(), combined = reader.readU64(), - flags = combined >> 56n; + flags = combined >> 56n, + numEntries = Number(combined & 0x00FFFFFFFFFFFFFFn); if (flags & 0x01n) throw new Error('Cluster summary uses unsupported sharded flag (0x01)'); - const numEntries = Number(combined & 0x00FFFFFFFFFFFFFFn); - clusterSummaries.push({ - firstEntry, - numEntries, - flags - }); + this.clusterSummaries.push({ firstEntry, numEntries, flags }); reader.seek(Number(recordStart + clusterSummaryRecordSize)); } reader.seek(Number(listStartOffset - clusterSummaryListSize)); - this.clusterSummaries = clusterSummaries; this._readNestedFrames(reader); - /* const checksumPagelist = */ reader.readU64(); + reader.readU64(); // checksumPagelist } _readNestedFrames(reader) { - const clusterPageLocations = [], - numListClusters = reader.readS64(); + const numListClusters = reader.readS64(), + numRecordCluster = reader.readU32(); if (numListClusters >= 0) throw new Error('Expected list frame for clusters'); - const numRecordCluster = reader.readU32(); + + this.pageLocations = []; for (let i = 0; i < numRecordCluster; ++i) { const outerListSize = reader.readS64(); @@ -177884,7 +180199,6 @@ class RNTupleDescriptorBuilder { const numElementsWithBit = reader.readS32(), hasChecksum = numElementsWithBit < 0, numElements = BigInt(Math.abs(Number(numElementsWithBit))), - locator = this._readLocator(reader); pages.push({ numElements, @@ -177894,11 +180208,8 @@ class RNTupleDescriptorBuilder { } const elementOffset = reader.readS64(), - isSuppressed = elementOffset < 0; - - let compression = null; - if (!isSuppressed) - compression = reader.readU32(); + isSuppressed = elementOffset < 0, + compression = isSuppressed ? null : reader.readU32(); columns.push({ pages, @@ -177908,113 +180219,43 @@ class RNTupleDescriptorBuilder { }); } - clusterPageLocations.push(columns); + this.pageLocations.push(columns); } - - this.pageLocations = clusterPageLocations; } - // Example Of Deserializing Page Content - deserializePage(blob, columnDescriptor, pageInfo) { - const originalColtype = columnDescriptor.coltype, - { - coltype - } = recontructUnsplitBuffer(blob, columnDescriptor); - let { - blob: processedBlob - } = recontructUnsplitBuffer(blob, columnDescriptor); - + /** @summary Search field by name + * @private */ + findField(name) { + for (let n = 0; n < this.fieldDescriptors.length; ++n) { + const field = this.fieldDescriptors[n]; + if (field.fieldName === name) + return field; + } + } - // Handle split index types - if (originalColtype === ENTupleColumnType.kSplitIndex32 || originalColtype === ENTupleColumnType.kSplitIndex64) { - const { - blob: decodedArray - } = DecodeDeltaIndex(processedBlob, coltype); - processedBlob = decodedArray; - } - - // Handle Split Signed Int types - if (originalColtype === ENTupleColumnType.kSplitInt16 || originalColtype === ENTupleColumnType.kSplitInt32 || originalColtype === ENTupleColumnType.kSplitInt64) { - const { - blob: decodedArray - } = decodeZigzag(processedBlob, coltype); - processedBlob = decodedArray; - } - - const reader = new RBufferReader(processedBlob), - values = [], - - // Use numElements from pageInfo parameter - numValues = Number(pageInfo.numElements), - // Helper for all simple types - extractValues = (readFunc) => { - for (let i = 0; i < numValues; ++i) - values.push(readFunc()); - }; - switch (coltype) { - case ENTupleColumnType.kBit: { - let bitCount = 0; - const totalBitsInBuffer = processedBlob.byteLength * 8; - if (totalBitsInBuffer < numValues) - throw new Error(`kBit: Not enough bits in buffer (${totalBitsInBuffer}) for numValues (${numValues})`); - - for (let byteIndex = 0; byteIndex < processedBlob.byteLength; ++byteIndex) { - const byte = reader.readU8(); - - // Extract 8 bits from this byte - for (let bitPos = 0; bitPos < 8 && bitCount < numValues; ++bitPos, ++bitCount) { - const bitValue = (byte >>> bitPos) & 1, - boolValue = bitValue === 1; - values.push(boolValue); - } - } - break; - } + /** @summary Return all childs of specified field + * @private */ + findChildFields(field) { + const indx = this.fieldDescriptors.indexOf(field), res = []; + for (let n = 0; n < this.fieldDescriptors.length; ++n) { + const fld = this.fieldDescriptors[n]; + if ((fld !== field) && (fld.parentFieldId === indx)) + res.push(fld); + } + return res; + } - case ENTupleColumnType.kReal64: - extractValues(reader.readF64.bind(reader)); - break; - case ENTupleColumnType.kReal32: - extractValues(reader.readF32.bind(reader)); - break; - case ENTupleColumnType.kInt64: - extractValues(reader.readS64.bind(reader)); - break; - case ENTupleColumnType.kUInt64: - extractValues(reader.readU64.bind(reader)); - break; - case ENTupleColumnType.kInt32: - extractValues(reader.readS32.bind(reader)); - break; - case ENTupleColumnType.kUInt32: - extractValues(reader.readU32.bind(reader)); - break; - case ENTupleColumnType.kInt16: - extractValues(reader.readS16.bind(reader)); - break; - case ENTupleColumnType.kUInt16: - extractValues(reader.readU16.bind(reader)); - break; - case ENTupleColumnType.kInt8: - extractValues(reader.readS8.bind(reader)); - break; - case ENTupleColumnType.kUInt8: - case ENTupleColumnType.kByte: - extractValues(reader.readU8.bind(reader)); - break; - case ENTupleColumnType.kChar: - extractValues(() => String.fromCharCode(reader.readS8())); - break; - case ENTupleColumnType.kIndex32: - extractValues(reader.readS32.bind(reader)); - break; - case ENTupleColumnType.kIndex64: - extractValues(reader.readS64.bind(reader)); - break; - default: - throw new Error(`Unsupported column type: ${columnDescriptor.coltype}`); + /** @summary Return array of columns for specified field + * @private */ + findColumns(field) { + const res = []; + if (!field) + return res; + for (const colDesc of this.columnDescriptors) { + if (this.fieldDescriptors[colDesc.fieldId] === field) + res.push(colDesc); } - return values; + return res; } } // class RNTupleDescriptorBuilder @@ -178025,15 +180266,15 @@ class RNTupleDescriptorBuilder { async function readHeaderFooter(tuple) { // if already read - return immediately, make possible to call several times if (tuple?.builder) - return true; + return tuple.builder; - if (!tuple.$file) - return false; + if (!tuple?.$file) + return null; // request header and footer buffers from the file return tuple.$file.readBuffer([tuple.fSeekHeader, tuple.fNBytesHeader, tuple.fSeekFooter, tuple.fNBytesFooter]).then(blobs => { if (blobs?.length !== 2) - return false; + throw new Error('Failure reading header or footer blobs'); // Handle both compressed and uncompressed cases const processBlob = (blob, uncompressedSize) => { @@ -178046,254 +180287,895 @@ async function readHeaderFooter(tuple) { return Promise.all([ processBlob(blobs[0], tuple.fLenHeader), processBlob(blobs[1], tuple.fLenFooter) - ]).then(unzip_blobs => { - const [header_blob, footer_blob] = unzip_blobs; - if (!header_blob || !footer_blob) - return false; - - tuple.builder = new RNTupleDescriptorBuilder; - tuple.builder.deserializeHeader(header_blob); - tuple.builder.deserializeFooter(footer_blob); - - // Build fieldToColumns mapping - tuple.fieldToColumns = {}; - for (const colDesc of tuple.builder.columnDescriptors) { - const fieldDesc = tuple.builder.fieldDescriptors[colDesc.fieldId], - fieldName = fieldDesc.fieldName; - if (!tuple.fieldToColumns[fieldName]) - tuple.fieldToColumns[fieldName] = []; - tuple.fieldToColumns[fieldName].push(colDesc); - } - - // Deserialize Page List - const group = tuple.builder.clusterGroups?.[0]; - if (!group || !group.pageListLocator) - throw new Error('No valid cluster group or page list locator found'); - - const offset = Number(group.pageListLocator.offset), - size = Number(group.pageListLocator.size), - uncompressedSize = Number(group.pageListLength); - - return tuple.$file.readBuffer([offset, size]).then(page_list_blob => { - if (!(page_list_blob instanceof DataView)) - throw new Error(`Expected DataView from readBuffer, got ${Object.prototype.toString.call(page_list_blob)}`); - - // Check if page list data is uncompressed - if (page_list_blob.byteLength === uncompressedSize) { - // Data is uncompressed, use directly - tuple.builder.deserializePageList(page_list_blob); - return true; - } - // Attempt to decompress the page list - return R__unzip(page_list_blob, uncompressedSize).then(unzipped_blob => { - if (!(unzipped_blob instanceof DataView)) - throw new Error(`Unzipped page list is not a DataView, got ${Object.prototype.toString.call(unzipped_blob)}`); - - tuple.builder.deserializePageList(unzipped_blob); - return true; - }); - }); - }); + ]); + }).then(unzip_blobs => { + const [header_blob, footer_blob] = unzip_blobs; + if (!header_blob || !footer_blob) + throw new Error('Failure when uncompress header and footer blobs'); + + tuple.builder = new RNTupleDescriptorBuilder; + tuple.builder.deserializeHeader(header_blob); + tuple.builder.deserializeFooter(footer_blob); + + // Deserialize Page List + const group = tuple.builder.clusterGroups?.[0]; + if (!group || !group.pageListLocator) + throw new Error('No valid cluster group or page list locator found'); + + const offset = Number(group.pageListLocator.offset), + size = Number(group.pageListLocator.size); + + return tuple.$file.readBuffer([offset, size]); + }).then(page_list_blob => { + if (!(page_list_blob instanceof DataView)) + throw new Error(`Expected DataView from readBuffer, got ${Object.prototype.toString.call(page_list_blob)}`); + + const group = tuple.builder.clusterGroups?.[0], + uncompressedSize = Number(group.pageListLength); + + // Check if page list data is uncompressed + if (page_list_blob.byteLength === uncompressedSize) + return page_list_blob; + + // Attempt to decompress the page list + return R__unzip(page_list_blob, uncompressedSize); + }).then(unzipped_blob => { + if (!(unzipped_blob instanceof DataView)) + throw new Error(`Unzipped page list is not a DataView, got ${Object.prototype.toString.call(unzipped_blob)}`); + + tuple.builder.deserializePageList(unzipped_blob); + return tuple.builder; }).catch(err => { console.error('Error during readHeaderFooter execution:', err); - throw err; + return null; }); } -function readEntry(rntuple, fieldName, entryIndex) { - const builder = rntuple.builder, - field = builder.fieldDescriptors.find(f => f.fieldName === fieldName), - fieldData = rntuple._clusterData[fieldName]; - if (!field) - throw new Error(`No descriptor for field ${fieldName}`); - if (!fieldData) - throw new Error(`No data for field ${fieldName}`); +/** @class Base class to read columns/fields from RNtuple + * @private */ + +class ReaderItem { + + constructor(column, name) { + this.column = null; + this.name = name; + this.id = -1; + this.coltype = 0; + this.sz = 0; + this.simple = true; + this.page = -1; // current page for the reading + + if (column?.coltype !== undefined) { + this.column = column; + this.id = column.index; + this.coltype = column.coltype; + + // special handling of split types + if ((this.coltype >= kSplitInt16) && (this.coltype <= kSplitIndex64)) { + this.coltype -= (kSplitInt16 - kInt16); + this.simple = false; + } + } else if (column?.length) + this.items = column; + } + + cleanup() { + this.views = null; + this.view = null; + this.view_len = 0; + } + + init_o() { + this.o = 0; + this.o2 = 0; // for bit count + if (this.column && this.views?.length) { + this.view = this.views.shift(); + this.view_len = this.view.byteLength; + } + } + + reset_extras() {} + + shift_o(sz) { + this.o += sz; + while ((this.o >= this.view_len) && this.view_len) { + this.o -= this.view_len; + if (this.views.length) { + this.view = this.views.shift(); + this.view_len = this.view.byteLength; + } else { + this.view = null; + this.view_len = 0; + } + } + } + + shift(entries) { + if (this.sz && this.simple) + this.shift_o(this.sz * entries); + else { + while (entries-- > 0) + this.func({}); + } + } + + /** @summary Simple column with fixed element size - no vectors, no strings */ + is_simple() { return this.sz && this.simple; } + + set_not_simple() { + this.simple = false; + this.items?.forEach(item => item.set_not_simple()); + } + + assignReadFunc() { + switch (this.coltype) { + case kBit: { + this.func = function(obj) { + if (this.o2 === 0) + this.byte = this.view.getUint8(this.o); + obj[this.name] = ((this.byte >>> this.o2++) & 1) === 1; + if (this.o2 === 8) { + this.o2 = 0; + this.shift_o(1); + } + }; + break; + } + case kReal64: + this.func = function(obj) { + obj[this.name] = this.view.getFloat64(this.o, LITTLE_ENDIAN); + this.shift_o(8); + }; + this.sz = 8; + break; + case kReal32: + this.func = function(obj) { + obj[this.name] = this.view.getFloat32(this.o, LITTLE_ENDIAN); + this.shift_o(4); + }; + this.sz = 4; + break; + case kReal16: + this.func = function(obj) { + const value = this.view.getUint16(this.o, LITTLE_ENDIAN); + this.shift_o(2); + // reimplementing of HalfToFloat + let fbits = (value & 0x8000) << 16, + abs = value & 0x7FFF; + if (abs) { + fbits |= 0x38000000 << (abs >= 0x7C00 ? 1 : 0); + for (; abs < 0x400; abs <<= 1, fbits -= 0x800000); + fbits += abs << 13; + } + this.buf.setUint32(0, fbits, true); + obj[this.name] = this.buf.getFloat32(0, true); + }; + this.sz = 2; + this.buf = new DataView(new ArrayBuffer(4), 0); + break; + case kReal32Trunc: + this.buf = new DataView(new ArrayBuffer(4), 0); + case kReal32Quant: + this.nbits = this.column.bitsOnStorage; + if (!this.buf) { + this.factor = (this.column.maxValue - this.column.minValue) / ((1 << this.nbits) - 1); + this.min = this.column.minValue; + } + + this.func = function(obj) { + let res = 0, len = this.nbits; + // extract nbits from the stream + while (len > 0) { + if (this.o2 === 0) { + this.byte = this.view.getUint8(this.o); + this.o2 = 8; // number of bits in the value + } + const pos = this.nbits - len; // extracted bits + if (len >= this.o2) { + res |= (this.byte & ((1 << this.o2) - 1)) << pos; // get all remaining bits + len -= this.o2; + this.o2 = 0; + this.shift_o(1); + } else { + res |= (this.byte & ((1 << len) - 1)) << pos; // get only len bits from the value + this.o2 -= len; + this.byte >>= len; + len = 0; + } + } + if (this.buf) { + this.buf.setUint32(0, res << (32 - this.nbits), true); + obj[this.name] = this.buf.getFloat32(0, true); + } else + obj[this.name] = res * this.factor + this.min; + }; + break; + case kInt64: + case kIndex64: + this.func = function(obj) { + // FIXME: let process BigInt in the TTree::Draw + obj[this.name] = Number(this.view.getBigInt64(this.o, LITTLE_ENDIAN)); + this.shift_o(8); + }; + this.sz = 8; + break; + case kUInt64: + this.func = function(obj) { + // FIXME: let process BigInt in the TTree::Draw + obj[this.name] = Number(this.view.getBigUint64(this.o, LITTLE_ENDIAN)); + this.shift_o(8); + }; + this.sz = 8; + break; + case kSwitch: + this.func = function(obj) { + // index not used in std::variant, may be in some other usecases + // obj[this.name] = Number(this.view.getBigInt64(this.o, LITTLE_ENDIAN)); + this.shift_o(8); // skip value, not used yet + obj[this.name] = this.view.getInt32(this.o, LITTLE_ENDIAN); + this.shift_o(4); + }; + this.sz = 12; + break; + case kInt32: + case kIndex32: + this.func = function(obj) { + obj[this.name] = this.view.getInt32(this.o, LITTLE_ENDIAN); + this.shift_o(4); + }; + this.sz = 4; + break; + case kUInt32: + this.func = function(obj) { + obj[this.name] = this.view.getUint32(this.o, LITTLE_ENDIAN); + this.shift_o(4); + }; + this.sz = 4; + break; + case kInt16: + this.func = function(obj) { + obj[this.name] = this.view.getInt16(this.o, LITTLE_ENDIAN); + this.shift_o(2); + }; + this.sz = 2; + break; + case kUInt16: + this.func = function(obj) { + obj[this.name] = this.view.getUint16(this.o, LITTLE_ENDIAN); + this.shift_o(2); + }; + this.sz = 2; + break; + case kInt8: + this.func = function(obj) { + obj[this.name] = this.view.getInt8(this.o); + this.shift_o(1); + }; + this.sz = 1; + break; + case kUInt8: + case kByte: + this.func = function(obj) { + obj[this.name] = this.view.getUint8(this.o); + this.shift_o(1); + }; + this.sz = 1; + break; + case kChar: + this.func = function(obj) { + obj[this.name] = String.fromCharCode(this.view.getInt8(this.o)); + this.shift_o(1); + }; + this.sz = 1; + break; + default: + throw new Error(`Unsupported column type: ${this.coltype}`); + } + } + + readStr(len) { + let s = ''; + while (len-- > 0) { + s += String.fromCharCode(this.view.getInt8(this.o)); + this.shift_o(1); + } + return s; + } + + collectPages(cluster_locations, dataToRead, itemsToRead, pagesToRead, emin, emax, elist) { + // no pages without real column id + if (!this.column || (this.id < 0)) + return; + + const pages = cluster_locations[this.id].pages; + + this.views = new Array(pages.length); + + let e0 = 0; + for (let p = 0; p < pages.length; ++p) { + const page = pages[p], + e1 = e0 + Number(page.numElements), + margin = this._is_offset_item ? 1 : 0, // offset for previous entry has to be read as well + is_inside = (e, beg, end) => (e >= beg) && (e < end + margin); + let is_entries_inside = false; + if (elist?.length) + elist.forEach(e => { is_entries_inside ||= is_inside(e, e0, e1); }); + else + is_entries_inside = is_inside(e0, emin, emax) || is_inside(e1, emin, emax) || is_inside(emin, e0, e1) || is_inside(emax, e0, e1); + + if (!this.is_simple() || is_entries_inside) { + itemsToRead.push(this); + dataToRead.push(Number(page.locator.offset), page.locator.size); + pagesToRead.push(p); + this.views[p] = null; // placeholder, filled after request + } else + this.views[p] = { byteLength: this.sz * Number(page.numElements) }; // dummy entry only to allow proper navigation + + e0 = e1; + } + } + + async unzipBlob(blob, cluster_locations, page_indx) { + const colEntry = cluster_locations[this.id], // Access column entry + numElements = Number(colEntry.pages[page_indx].numElements), + elementSize = this.column.bitsOnStorage / 8, + expectedSize = Math.ceil(numElements * elementSize); + + // Check if data is compressed + if ((colEntry.compression === 0) || (blob.byteLength === expectedSize)) + return blob; // Uncompressed: use blob directly + + // Try decompression + return R__unzip(blob, expectedSize).then(result => { + return result || blob; // Fallback to original blob ?? + }).catch(err => { + throw new Error(`Failed to unzip page ${page_indx} for column ${this.id}: ${err.message}`); + }); + } + + reconstructBlob(rawblob, page_indx) { + if (!(rawblob instanceof DataView)) + throw new Error(`Invalid blob type for column ${this.id}: ${Object.prototype.toString.call(rawblob)}`); + + const originalColtype = this.column.coltype, + view = recontructUnsplitBuffer(rawblob, originalColtype); + + // Handle split index types + switch (originalColtype) { + case kSplitIndex32: decodeIndex32(view); break; + case kSplitIndex64: decodeIndex64(view, 0); break; + case kSwitch: decodeIndex64(view, 4); break; + case kSplitInt16: decodeZigzag16(view); break; + case kSplitInt32: decodeZigzag32(view); break; + case kSplitInt64: decodeZigzag64(view); break; + } + + this.views[page_indx] = view; + } + +} + + +/** @class reading std::string field + * @private */ + +class StringReaderItem extends ReaderItem { + + constructor(items, name) { + super(items, name); + items[0]._is_offset_item = true; + items[1].set_not_simple(); + this.off0 = 0; + } + + reset_extras() { + this.off0 = 0; + } + + func(tgtobj) { + const tmp = {}; + this.items[0].func(tmp); + const off = Number(tmp.len); + tgtobj[this.name] = this.items[1].readStr(off - this.off0); + this.off0 = off; + } - // Detect and decode string fields - if (Array.isArray(fieldData) && fieldData.length === 2) { - const [offsets, payload] = fieldData, - start = entryIndex === 0 ? 0 : Number(offsets[entryIndex - 1]), - end = Number(offsets[entryIndex]), - decoded = payload.slice(start, end).join(''); // Convert to string - return decoded; + shift(entries) { + this.items[0].shift(entries - 1); + const tmp = {}; + this.items[0].func(tmp); + const off = Number(tmp.len); + this.items[1].shift_o(off - this.off0); + this.off0 = off; } - // Fallback: primitive type (e.g. int, float) - return fieldData[0][entryIndex]; } -/** @summary Return field name for specified branch index - * @desc API let use field name in selector or field object itself */ -function getSelectorFieldName(selector, i) { - const br = selector.getBranch(i); - return isStr(br) ? br : br?.fieldName; +/** @class reading Streamed field + * @private */ + +class StreamedReaderItem extends ReaderItem { + + constructor(items, name, file, classname) { + super(items, name); + items[0]._is_offset_item = true; + items[1].set_not_simple(); + this.file = file; + this.classname = classname; + this.off0 = 0; + } + + reset_extras() { + this.off0 = 0; + } + + func(tgtobj) { + const tmp = {}, res = {}; + this.items[0].func(tmp); + const off = Number(tmp.len), + buf = new TBuffer(this.items[1].view, this.items[1].o, this.file, this.items[1].o + off - this.off0); + + // TODO: if by chance object splited between two pages + if (this.items[1].view.byteLength < this.items[1].o + off - this.off0) + console.error('FAILURE - buffer is splitted, need to be read from next page'); + + buf.classStreamer(res, this.classname); + + this.items[1].shift_o(off - this.off0); + this.off0 = off; + tgtobj[this.name] = res; + } + + shift(entries) { + this.items[0].shift(entries - 1); + const tmp = {}; + this.items[0].func(tmp); + const off = Number(tmp.len); + this.items[1].shift_o(off - this.off0); + this.off0 = off; + } + } -// Read and process the next data cluster from the RNTuple -function readNextCluster(rntuple, selector) { - const builder = rntuple.builder; - // Add validation - if (!builder.clusterSummaries || builder.clusterSummaries.length === 0) - throw new Error('No cluster summaries available - possibly incomplete file reading'); +/** @class reading of std::array + * @private */ - const clusterIndex = selector.currentCluster, - clusterSummary = builder.clusterSummaries[clusterIndex], - // Gather all pages for this cluster from selected fields only - pages = [], - // Collect only selected field names from selector - selectedFields = []; +class ArrayReaderItem extends ReaderItem { - for (let i = 0; i < selector.numBranches(); ++i) - selectedFields.push(getSelectorFieldName(selector, i)); + constructor(items, tgtname, arrsize) { + super(items, tgtname); + this.arrsize = arrsize; + items[0].set_not_simple(); + } - // For each selected field, collect its columns' pages - for (const fieldName of selectedFields) { - const columns = rntuple.fieldToColumns[fieldName]; - if (!columns) - throw new Error(`Selected field '${fieldName}' not found in RNTuple`); + func(tgtobj) { + const arr = [], tmp = {}; + let len = this.arrsize; + while (len-- > 0) { + this.items[0].func(tmp); + arr.push(tmp.value); + } + tgtobj[this.name] = arr; + } - for (const colDesc of columns) { - const colEntry = builder.pageLocations[clusterIndex]?.[colDesc.index]; + shift(entries) { + this.items[0].shift(entries * this.arrsize); + } + +} + + +/** @class reading of std::bitset + * @desc large numbers with more than 48 bits converted to BigInt + * @private */ - // When the data is missing or broken - if (!colEntry || !colEntry.pages) - throw new Error(`No pages for column ${colDesc.index} in cluster ${clusterIndex}`); +class BitsetReaderItem extends ReaderItem { - for (const page of colEntry.pages) - pages.push({ page, colDesc, fieldName }); + constructor(items, tgtname, size) { + super(items, tgtname); + this.size = size; + items[0].set_not_simple(); + this.bigint = size > 48; + } + + func(tgtobj) { + const tmp = {}; + let len = 0, res = this.bigint ? 0n : 0; + while (len < this.size) { + this.items[0].func(tmp); + if (tmp.bit) { + if (this.bigint) + res |= (1n << BigInt(len)); + else + res |= 1 << len; + } + len++; } + tgtobj[this.name] = res; } - selector.currentCluster++; + shift(entries) { + this.items[0].shift(entries * this.size); + } - // Early exit if no pages to read (i.e., no selected fields matched) - if (pages.length === 0) { - selector.Terminate(false); - return Promise.resolve(); - } - - // Build flat array of [offset, size, offset, size, ...] to read pages - const dataToRead = pages.flatMap(p => - [Number(p.page.locator.offset), Number(p.page.locator.size)] - ); - - return rntuple.$file.readBuffer(dataToRead).then(blobsRaw => { - const blobs = Array.isArray(blobsRaw) ? blobsRaw : [blobsRaw], - unzipPromises = blobs.map((blob, idx) => { - const { page, colDesc } = pages[idx], - colEntry = builder.pageLocations[clusterIndex][colDesc.index], // Access column entry - numElements = Number(page.numElements), - elementSize = colDesc.bitsOnStorage / 8; - - // Check if data is compressed - if (colEntry.compression === 0) - return Promise.resolve(blob); // Uncompressed: use blob directly - const expectedSize = numElements * elementSize; - - // Special handling for boolean fields - if (colDesc.coltype === ENTupleColumnType.kBit) { - const expectedBoolSize = Math.ceil(numElements / 8); - if (blob.byteLength === expectedBoolSize) - return Promise.resolve(blob); - // Try decompression but catch errors for boolean fields - return R__unzip(blob, expectedBoolSize).catch(err => { - throw new Error(`Failed to unzip boolean page ${idx}: ${err.message}`); - }); - } +} - // If the blob is already the expected size, treat as uncompressed - if (blob.byteLength === expectedSize) - return Promise.resolve(blob); - - // Try decompression - return R__unzip(blob, expectedSize).then(result => { - if (!result) - return blob; // Fallback to original blob - return result; - }).catch(err => { - throw new Error(`Failed to unzip page ${idx}: ${err.message}`); - }); - }); - return Promise.all(unzipPromises).then(unzipBlobs => { - rntuple._clusterData = {}; // store deserialized data per field - - for (let i = 0; i < unzipBlobs.length; ++i) { - const blob = unzipBlobs[i]; - // Ensure blob is a DataView - if (!(blob instanceof DataView)) - throw new Error(`Invalid blob type for page ${i}: ${Object.prototype.toString.call(blob)}`); - const { - page, - colDesc - } = pages[i], - field = builder.fieldDescriptors[colDesc.fieldId], - values = builder.deserializePage(blob, colDesc, page); - - // Support multiple representations (e.g., string fields with offsets + payload) - if (!rntuple._clusterData[field.fieldName]) - rntuple._clusterData[field.fieldName] = []; - - // splitting string fields into offset and payload components - if (field.typeName === 'std::string') { - if ( - colDesc.coltype === ENTupleColumnType.kIndex64 || - colDesc.coltype === ENTupleColumnType.kIndex32 || - colDesc.coltype === ENTupleColumnType.kSplitIndex64 || - colDesc.coltype === ENTupleColumnType.kSplitIndex32 - ) // Index64/Index32 - rntuple._clusterData[field.fieldName][0] = values; // Offsets - else if (colDesc.coltype === ENTupleColumnType.kChar) - rntuple._clusterData[field.fieldName][1] = values; // Payload - else - throw new Error(`Unsupported column type for string field: ${colDesc.coltype}`); - } else - rntuple._clusterData[field.fieldName][0] = values; +/** @class reading std::vector and other kinds of collections + * @private */ + +class CollectionReaderItem extends ReaderItem { + + constructor(items, tgtname) { + super(items, tgtname); + this.off0 = 0; + items[0]._is_offset_item = true; + items[1].set_not_simple(); + } + + reset_extras() { + this.off0 = 0; + } + + func(tgtobj) { + const arr = [], tmp = {}; + this.items[0].func(tmp); + const off = Number(tmp.len); + let len = off - this.off0; + while (len-- > 0) { + this.items[1].func(tmp); + arr.push(tmp.val); + } + tgtobj[this.name] = arr; + this.off0 = off; + } + + shift(entries) { + const tmp = {}; + this.items[0].shift(entries - 1); + this.items[0].func(tmp); + const off = Number(tmp.len); + this.items[1].shift(off - this.off0); + this.off0 = off; + } + +} + +/** @class reading std::variant field + * @private */ + +class VariantReaderItem extends ReaderItem { + + constructor(items, tgtname) { + super(items, tgtname); + this.set_not_simple(); + } + + func(tgtobj) { + const tmp = {}; + this.items[0].func(tmp); + const id = tmp.switch; + if (id === 0) + tgtobj[this.name] = null; // set null + else if (Number.isInteger(id) && (id > 0) && (id < this.items.length)) + this.items[id].func(tgtobj); + } + +} + + +/** @class reading std::tuple<> field + * @private */ + +class TupleReaderItem extends ReaderItem { + + func(tgtobj) { + const tuple = {}; + this.items.forEach(item => item.func(tuple)); + tgtobj[this.name] = tuple; + } + + shift(entries) { + this.items.forEach(item => item.shift(entries)); + } + +} + +/** @class reading custom class field + * @private */ + +class CustomClassReaderItem extends ReaderItem { + + constructor(items, tgtname, classname) { + super(items, tgtname); + this.classname = classname; + this.set_not_simple(); + } + + func(tgtobj) { + const obj = { _typename: this.classname }; + this.items.forEach(item => item.func(obj)); + tgtobj[this.name] = obj; + } + + shift(entries) { + this.items.forEach(item => item.shift(entries)); + } + +} + + +/** @class reading std::pair field + * @private */ + +class PairReaderItem extends ReaderItem { + + func(tgtobj) { + const res = {}; + this.items[0].func(res); + this.items[1].func(res); + tgtobj[this.name] = res; + } + + shift(entries) { + this.items[0].shift(entries); + this.items[1].shift(entries); + } + +} + + +async function rntupleProcess(rntuple, selector, args = {}) { + const handle = { + file: rntuple.$file, // keep file reference + columns: [], // list of ReaderItem with real columns for reading + items: [], // list of ReaderItem producing output fields + current_cluster: 0, // current cluster to process + current_cluster_first_entry: 0, // first entry in current cluster + current_cluster_last_entry: 0, // last entry in current cluster + current_entry: 0, // current processed entry + process_arrays: false, // one can process all branches as arrays + firstentry: 0, // first entry in the rntuple + lastentry: 0 // last entry in the rntuple + }; + + function readNextPortion(builder, inc_cluster) { + let do_again = true, numClusterEntries, locations; + + while (do_again) { + if (inc_cluster) { + handle.current_cluster++; + handle.current_cluster_first_entry = handle.current_cluster_last_entry; } - // Ensure string fields have ending offset for proper reconstruction of the last entry - for (const fieldName of selectedFields) { - const field = builder.fieldDescriptors.find(f => f.fieldName === fieldName), - colData = rntuple._clusterData[fieldName]; - if (field.typeName === 'std::string') { - if (!Array.isArray(colData) || colData.length !== 2) - throw new Error(`String field '${fieldName}' must have 2 columns`); - if (colData[0].length !== builder.clusterSummaries[clusterIndex].numEntries) - throw new Error(`Malformed string field '${fieldName}': missing final offset`); - } + locations = builder.pageLocations[handle.current_cluster]; + if (!locations) { + selector.Terminate(true); + return selector; } - const numEntries = clusterSummary.numEntries; - for (let i = 0; i < numEntries; ++i) { - for (let b = 0; b < selector.numBranches(); ++b) { - const fieldName = getSelectorFieldName(selector, b), - tgtName = selector.nameOfBranch(b), - values = rntuple._clusterData[fieldName]; + numClusterEntries = builder.clusterSummaries[handle.current_cluster].numEntries; + + handle.current_cluster_last_entry = handle.current_cluster_first_entry + numClusterEntries; + + do_again = inc_cluster && handle.process_entries && + (handle.process_entries[handle.process_entries_indx] >= handle.current_cluster_last_entry); + } + + // calculate entries which can be extracted from the cluster + let emin, emax; + const dataToRead = [], itemsToRead = [], pagesToRead = [], elist = []; - if (!values) - throw new Error(`Missing values for selected field: ${fieldName}`); - selector.tgtobj[tgtName] = readEntry(rntuple, fieldName, i); + if (handle.process_entries) { + let i = handle.process_entries_indx; + while ((i < handle.process_entries.length) && (handle.process_entries[i] < handle.current_cluster_last_entry)) + elist.push(handle.process_entries[i++] - handle.current_cluster_first_entry); + emin = elist[0]; + emax = elist[elist.length - 1]; + } else { + emin = handle.current_entry - handle.current_cluster_first_entry; + emax = Math.min(numClusterEntries, handle.process_max - handle.current_cluster_first_entry); + } + + // loop over all columns and request required pages + handle.columns.forEach(item => item.collectPages(locations, dataToRead, itemsToRead, pagesToRead, emin, emax, elist)); + + return rntuple.$file.readBuffer(dataToRead).then(blobsRaw => { + const blobs = Array.isArray(blobsRaw) ? blobsRaw : [blobsRaw], + unzipPromises = blobs.map((blob, idx) => itemsToRead[idx].unzipBlob(blob, locations, pagesToRead[idx])); + return Promise.all(unzipPromises); + }).then(unzipBlobs => { + unzipBlobs.map((rawblob, idx) => itemsToRead[idx].reconstructBlob(rawblob, pagesToRead[idx])); + + // reset reading pointer after all buffers are there + handle.columns.forEach(item => item.init_o()); + handle.items.forEach(item => item.reset_extras()); + + let skip_entries = handle.current_entry - handle.current_cluster_first_entry; + + while (handle.current_entry < handle.current_cluster_last_entry) { + for (let i = 0; i < handle.items.length; ++i) { + if (skip_entries > 0) + handle.items[i].shift(skip_entries); + handle.items[i].func(selector.tgtobj); + } + skip_entries = 0; + + selector.Process(handle.current_entry); + + if (handle.process_entries) { + if (++handle.process_entries_indx >= handle.process_entries.length) { + selector.Terminate(true); + return selector; + } + const prev_entry = handle.current_entry; + handle.current_entry = handle.process_entries[handle.process_entries_indx]; + skip_entries = handle.current_entry - prev_entry - 1; + } else if (++handle.current_entry >= handle.process_max) { + selector.Terminate(true); + return selector; } - selector.Process(); } - selector.Terminate(true); + return readNextPortion(builder, true); }); - }); -} + } + + function addColumnReadout(column, tgtname) { + const item = new ReaderItem(column, tgtname); + item.assignReadFunc(); + handle.columns.push(item); + return item; + } + + function addFieldReading(builder, field, tgtname) { + const columns = builder.findColumns(field), + childs = builder.findChildFields(field); + if (!columns?.length) { + if ((childs.length === 2) && (field.typeName.indexOf('std::pair') === 0)) { + const item1 = addFieldReading(builder, childs[0], 'first'), + item2 = addFieldReading(builder, childs[1], 'second'); + return new PairReaderItem([item1, item2], tgtname); + } + + if ((childs.length === 1) && (field.typeName.indexOf('std::array') === 0)) { + const item1 = addFieldReading(builder, childs[0], 'value'); + return new ArrayReaderItem([item1], tgtname, Number(field.arraySize)); + } + + if ((childs.length === 1) && (field.typeName.indexOf('std::atomic') === 0)) + return addFieldReading(builder, childs[0], tgtname); + + + if ((childs.length > 0) && (field.typeName.indexOf('std::tuple') === 0)) { + const items = []; + for (let i = 0; i < childs.length; ++i) + items.push(addFieldReading(builder, childs[i], `_${i}`)); + return new TupleReaderItem(items, tgtname); + } -// TODO args can later be used to filter fields, limit entries, etc. -// Create reader and deserialize doubles from the buffer -function rntupleProcess(rntuple, selector, args) { - return readHeaderFooter(rntuple).then(() => { - selector.Begin(); - selector.currentCluster = 0; - return readNextCluster(rntuple, selector); + // this is custom class which is decomposed on several fields + if ((childs.length > 0) && field.checksum && field.typeName) { + const items = []; + for (let i = 0; i < childs.length; ++i) + items.push(addFieldReading(builder, childs[i], childs[i].fieldName)); + return new CustomClassReaderItem(items, tgtname, field.typeName); + } + + throw new Error(`No columns found for field '${field.fieldName}' in RNTuple`); + } + + if ((columns.length === 2) && (field.typeName === 'std::string')) { + const itemlen = addColumnReadout(columns[0], 'len'), + itemstr = addColumnReadout(columns[1], 'str'); + return new StringReaderItem([itemlen, itemstr], tgtname); + } + + if ((columns.length === 1) && (field.typeName.indexOf('std::bitset') === 0)) { + const itembit = addColumnReadout(columns[0], 'bit'); + return new BitsetReaderItem([itembit], tgtname, Number(field.arraySize)); + } + + if ((columns.length === 2) && field.checksum && field.typeName) { + if (!handle.file.getStreamer(field.typeName, { checksum: field.checksum })) + throw new Error(`No streamer for type '${field.typeName}' checksum ${field.checksum}`); + + const itemlen = addColumnReadout(columns[0], 'len'), + itemb = addColumnReadout(columns[1], 'b'); + return new StreamedReaderItem([itemlen, itemb], tgtname, handle.file, field.typeName); + } + + let is_stl = false; + ['vector', 'map', 'unordered_map', 'multimap', 'unordered_multimap', 'set', 'unordered_set', 'multiset', 'unordered_multiset'].forEach(name => { + if (field.typeName.indexOf('std::' + name) === 0) + is_stl = true; + }); + + if ((childs.length === 1) && is_stl) { + const itemlen = addColumnReadout(columns[0], 'len'), + itemval = addFieldReading(builder, childs[0], 'val'); + return new CollectionReaderItem([itemlen, itemval], tgtname); + } + + if ((childs.length > 0) && (field.typeName.indexOf('std::variant') === 0)) { + const items = [addColumnReadout(columns[0], 'switch')]; + for (let i = 0; i < childs.length; ++i) + items.push(addFieldReading(builder, childs[i], tgtname)); + return new VariantReaderItem(items, tgtname); + } + + return addColumnReadout(columns[0], tgtname); + } + + return readHeaderFooter(rntuple).then(builder => { + if (!builder) + throw new Error('Not able to read header for the RNtuple'); + + for (let i = 0; i < selector.numBranches(); ++i) { + const br = selector.getBranch(i), + name = isStr(br) ? br : br?.fieldName, + tgtname = selector.nameOfBranch(i); + if (!name) + throw new Error(`Not able to extract name for field ${i}`); + + const field = builder.findField(name); + if (!field) + throw new Error(`Field ${name} not found`); + + const item = addFieldReading(builder, field, tgtname); + handle.items.push(item); + } + + // calculate number of entries + builder.clusterSummaries.forEach(summary => { handle.lastentry += summary.numEntries; }); + + if (handle.firstentry >= handle.lastentry) + throw new Error('Not able to find entries in the RNtuple'); + + // select range of entries to process + handle.process_min = handle.firstentry; + handle.process_max = handle.lastentry; + + if (args.elist) { + args.firstentry = args.elist.at(0); + args.numentries = args.elist.at(-1) - args.elist.at(0) + 1; + handle.process_entries = args.elist; + handle.process_entries_indx = 0; + handle.process_arrays = false; // do not use arrays process for selected entries + } + + if (Number.isInteger(args.firstentry) && (args.firstentry > handle.firstentry) && (args.firstentry < handle.lastentry)) + handle.process_min = args.firstentry; + + if (Number.isInteger(args.numentries) && (args.numentries > 0)) + handle.process_max = Math.min(handle.process_max, handle.process_min + args.numentries); + + // first check from which cluster one should start + for (let indx = 0, emin = 0; indx < builder.clusterSummaries.length; ++indx) { + const summary = builder.clusterSummaries[indx], + emax = emin + summary.numEntries; + if ((handle.process_min >= emin) && (handle.process_min < emax)) { + handle.current_cluster = indx; + handle.current_cluster_first_entry = emin; + break; + } + emin = emax; + } + + if (handle.current_cluster < 0) + throw new Error(`Not able to find cluster for entry ${handle.process_min} in the RNtuple`); + + handle.current_entry = handle.process_min; + + selector.Begin(rntuple); + + return readNextPortion(builder); }).then(() => selector); } + class TDrawSelectorTuple extends TDrawSelector { /** @summary Return total number of entries @@ -178306,11 +181188,7 @@ class TDrawSelectorTuple extends TDrawSelector { /** @summary Search for field in tuple * @desc TODO: Can be more complex when name includes extra parts referencing member or collection size or more */ - findBranch(tuple, name) { - return tuple.builder?.fieldDescriptors.find(field => { - return field.fieldName === name; - }); - } + findBranch(tuple, name) { return tuple.builder?.findField(name); } /** @summary Returns true if field can be used as array */ isArrayBranch(/* tuple, br */) { return false; } @@ -178340,8 +181218,8 @@ async function rntupleDraw(rntuple, args) { args.SelectorClass = TDrawSelectorTuple; args.processFunction = rntupleProcess; - return readHeaderFooter(rntuple).then(res_header_footer => { - return res_header_footer ? treeDraw(rntuple, args) : null; + return readHeaderFooter(rntuple).then(builder => { + return builder ? treeDraw(rntuple, args) : null; }); } @@ -178352,12 +181230,10 @@ async function rntupleDraw(rntuple, args) { async function tupleHierarchy(tuple_node, tuple) { tuple_node._childs = []; // tuple_node._tuple = tuple; // set reference, will be used later by RNTuple::Draw - - return readHeaderFooter(tuple).then(res => { - if (!res) - return res; - - tuple.builder?.fieldDescriptors.forEach(field => { + return readHeaderFooter(tuple).then(builder => { + builder?.fieldDescriptors.forEach((field, indx) => { + if (field.parentFieldId !== indx) + return; const item = { _name: field.fieldName, _typename: 'ROOT::RNTupleField', // pseudo class name, used in draw.mjs @@ -178366,20 +181242,16 @@ async function tupleHierarchy(tuple_node, tuple) { $tuple: tuple, // reference on tuple, need for drawing $field: field }; - item._obj = item; - tuple_node._childs.push(item); }); - - return true; + return Boolean(builder); }); } var rntuple = /*#__PURE__*/Object.freeze({ __proto__: null, RBufferReader: RBufferReader, -readEntry: readEntry, readHeaderFooter: readHeaderFooter, rntupleDraw: rntupleDraw, rntupleProcess: rntupleProcess, @@ -178394,13 +181266,15 @@ async function drawRNTuple(dom, obj, opt) { const args = {}; let tuple; - if (obj?.$tuple) { + if (obj?.$tuple && obj.$field) { // case of fictional ROOT::RNTupleField tuple = obj.$tuple; args.expr = obj._name; - if (isStr(opt) && opt.indexOf('dump') === 0) + if (isStr(opt) && opt.indexOf('dump') === 0) { args.expr += '>>' + opt; - else if (opt) + args.branch = obj.$field; + args.copy_fields = false; // no need to copy fields, reading is simple + } else if (opt) args.expr += opt; } else { tuple = obj; @@ -178918,7 +181792,7 @@ class RAxisPainter extends RObjectPainter { this.logbase = Math.exp(1); else if (_log > 1.9) this.logbase = Math.round(_log); - this.func = log().base(this.logbase).domain([smin, smax]); + this.func = log$1().base(this.logbase).domain([smin, smax]); } else this.func = linear().domain([smin, smax]); @@ -183347,7 +186221,7 @@ class RCanvasPainter extends RPadPainter { /** @summary Function called when canvas menu item Save is called */ saveCanvasAsFile(fname) { - const pnt = fname.indexOf('.'); + const pnt = fname.lastIndexOf('.'); this.createImage(fname.slice(pnt + 1)) .then(res => this.sendWebsocket(`SAVE:${fname}:${res}`)); } @@ -184942,6 +187816,7 @@ exports.getAbsPosInCanvas = getAbsPosInCanvas; exports.getActivePad = getActivePad; exports.getBoxDecorations = getBoxDecorations; exports.getColor = getColor; +exports.getColorPalette = getColorPalette; exports.getDocument = getDocument; exports.getDomCanvasPainter = getDomCanvasPainter; exports.getElementCanvPainter = getElementCanvPainter; @@ -185001,6 +187876,7 @@ exports.registerMethods = registerMethods; exports.resize = resize; exports.selectActivePad = selectActivePad; exports.setBatchMode = setBatchMode; +exports.setColorPalette = setColorPalette; exports.setDefaultDrawOpt = setDefaultDrawOpt; exports.setHPainter = setHPainter; exports.setHistogramTitle = setHistogramTitle; diff --git a/js/changes.md b/js/changes.md index 7e7f905a1e9f3..7ddc3cf6c956a 100644 --- a/js/changes.md +++ b/js/changes.md @@ -2,10 +2,52 @@ ## Changes in dev +1. Implement new data types in `RNtuple` + - reduced float types kFloat16, kReal32Trunc, kReal32Quant + - `std::vector` + - `std::map`, `std::unordered_map`, `std::multimap`, `std::unordered_multimap` with `std::pair` + - `std::set`, `std::unordered_set`, `std::multiset`, `std::unordered_multiset` + - `std::array` + - `std::variant` + - `std::tuple` + - `std::bitset` + - `std::atomic` + - simple custom classes + - streamed types +1. Resort order of ranges in http request, fixing several long-standing problems #374 1. Implement for `TPie` 3d, text, title drawing including interactivity -1. Remove support for deprectaed TH1K class +1. Implement `TCanvas` support in `build3d` function #373 +1. Implements `TTree` branches filtering via context menu #364 +1. Let define alternative draw function #378 +1. Implement padsN draw option for `THStack` and `TMultiGraph` +1. Support custom click handler for `TGraph` https://root-forum.cern.ch/t/64744 +1. Correctly draw axis ticks when `fNdivisions` is negative +1. Use `resvg-js` backend for PNG support in node.js #391, thanks to https://github.com/OmarMesqq +1. Introduce `settings.ServerTimeout` global timeout for THttpServer operations +1. Let set custom color palette with `setColorPalette` function +1. Upgrade three.js r180 -> r183 +1. Remove support for deprectaed `TH1K` class +1. Fix - paint frame border mode/size from `TCanvas` +1. Fix - interactivity for TH3 palette drawing #398 + + +## Changes in 7.10.3 +1. Fix - add `TLeafG` support in `TTree` #397 +2. Fix - reset contour while drawing `TH3` +3. Fix - fix kFloat16/kDouble32 processing in `TTree` + + +## Changes in 7.10.2 +1. Fix - correctly process `TLeafB` arrays in tree draw #384 +2. Fix - better detect default ranges in `TGraph` histogram +3. Fix - convert BigInt before `RNtuple` drawing +4. Fix - pages and clusters processing in `RNtuple` #390 +5. Fix - extra row for legend header, proper horizontal align https://github.com/root-project/root/issues/21173 + + +## Changes in 7.10.1 1. Fix - proper paint axis labels on both sides when pad.fTickx/y = 2 -1. Fix - paint frame border mode/size from TCanvas +2. Fix - recover io after bad http response ## Changes in 7.10.0 @@ -1469,11 +1511,11 @@ 8. Fix several problems with markers drawing; implement plus, asterisk, mult symbols. 9. Implement custom layout, which allows to configure user-defined layout for displayed objects 10. Fix errors with scaling of axis labels. -11. Support also Y axis with custom labels like: http://jsroot.gsi.de/dev/?nobrowser&file=../files/atlas.root&item=LEDShapeHeightCorr_Gain0;1&opt=col +11. Support also Y axis with custom labels like: https://jsroot.gsi.de/dev/?nobrowser&file=https://jsroot.gsi.de/files/atlas.root&item=LEDShapeHeightCorr_Gain0;1&opt=col ## Changes in 3.7 -1. Support of X axis with custom labels like: http://jsroot.gsi.de/dev/?nobrowser&json=../files/hist_xlabels.json +1. Support of X axis with custom labels like: https://jsroot.gsi.de/dev/?nobrowser&json=https://jsroot.gsi.de/files/hist_xlabels.json 2. Extend functionality of JSROOT.addDrawFunc() function. One could register type-specific `make_request` and `after_request` functions; `icon`, `prereq`, `script`, `monitor` properties. This let add more custom elements to the generic gui, implemented with JSROOT.HierarchyPainter @@ -1660,7 +1702,7 @@ 13. Provide example fileitem.htm how read and display item from ROOT file. 14. In default index.htm page one could specify 'file', 'layout', 'item' and 'items' parameters like: - + 15. Support direct reading of objects from sub-sub-directories. 16. Introduce demo.htm, which demonstrates online usage of JSROOT. 17. One could use demo.htm directly with THttpServer providing address like: diff --git a/js/index.htm b/js/index.htm index cd123332065fa..fb99f5640b8e8 100644 --- a/js/index.htm +++ b/js/index.htm @@ -14,7 +14,7 @@ -
+
loading modules ...